Toggle Button Timeout Using Millis()

Here is the state change version of the code using the Bounce2 library for debounced button transitions. The library is available through the library manager. The press and hold buttons work when the toggle buttons have timed out.

I'm sure the code can be tidied up with use of arrays.

byte relay1 = 0;
byte relay2 = 1;
byte relay3 = 2;
byte relay4 = 3;

byte button_1 = 4;
byte togglebutton_1 = 5;
byte button_2 = 6;
byte togglebutton_2 = 7;

//variables to control state and timeout after toggle button press
boolean timing1 = false;
boolean timing2 = false;
unsigned long startTime1;
unsigned long startTime2;
unsigned long runTime1 = 5000;
unsigned long runTime2 = 5000;

#include <Bounce2.h> //available through ide library manager
//create 4 Bounce objects
Bounce button1 = Bounce();
Bounce togglebutton1 = Bounce();
Bounce button2 = Bounce();
Bounce togglebutton2 = Bounce();

void setup() {
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  //Test led for timing check of relay outputs
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  //set up button pin Bounce objects
  pinMode (button_1, INPUT_PULLUP);
  button1.attach(button_1);
  button1.interval(50);//debounce interval

  pinMode (togglebutton_1, INPUT_PULLUP);
  togglebutton1.attach(togglebutton_1);
  togglebutton1.interval(50);//debounce interval

  pinMode (button_2, INPUT_PULLUP);
  button2.attach(button_2);
  button2.interval(50);//debounce interval

  pinMode (togglebutton_2, INPUT_PULLUP);
  togglebutton2.attach(togglebutton_2 );
  togglebutton2.interval(50);//debounce interval
}

void loop() {
  //.update() key function of Bounce2 library that checks for debounced state of pins and any transitions
  button1.update();
  togglebutton1.update();
  button2.update();
  togglebutton2.update();

  if (button1.fell())//state change to pressed
  {
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite (13, LOW);
  }

  if (button1.rose())//state change to released
  {
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    digitalWrite (13, HIGH);
  }

  if (togglebutton1.fell())
  {
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite(13, LOW);
    timing1 = true;
    startTime1 = millis();
  }

  if (timing1 == true && millis() - startTime1 >= runTime1) //togglebutton1 timed out
  {
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    digitalWrite(13, HIGH);
    timing1 = false;
  }

  if (button2.fell())
  {
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite(relay3, LOW);
    digitalWrite(relay4, LOW);
    digitalWrite(13, LOW);
  }

  if (button2.rose())
  {
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    digitalWrite(relay3, HIGH);
    digitalWrite(relay4, HIGH);
    digitalWrite(13, HIGH);
  }

  if (togglebutton2.fell())
  {
    digitalWrite(relay1, LOW);
    digitalWrite(relay2, LOW);
    digitalWrite(relay3, LOW);
    digitalWrite(relay4, LOW);
    digitalWrite(13, LOW);
    timing2 = true;
    startTime2 = millis();
  }

  if (timing2 == true && millis() - startTime2 >= runTime2)
  {
    digitalWrite(relay1, HIGH);
    digitalWrite(relay2, HIGH);
    digitalWrite(relay3, HIGH);
    digitalWrite(relay4, HIGH);
    digitalWrite(13, HIGH);
    timing2 = false;
  }
}