docs: @Override
      protected void uploadTusFiles() throws IOException, ProtocolException {
          setState(State.UPLOADING);
          while (uploads.size() > 0) {
              final TusUploader tusUploader;
              // don't recreate uploader if it already exists.
              // this is to avoid multiple connections being open. And to avoid some connections left unclosed.
              if (lastTusUploader != null) {
                  tusUploader = lastTusUploader;
                  lastTusUploader = null;
              } else {
                  tusUploader = tusClient.resumeOrCreateUpload(uploads.get(0));
                  if (getUploadChunkSize() > 0) {
                      tusUploader.setChunkSize(getUploadChunkSize());
                  }
              }
  
              TusExecutor tusExecutor = new TusExecutor() {
                  @Override
                  protected void makeAttempt() throws ProtocolException, IOException {
                      while (state == State.UPLOADING) {
                          int chunkUploaded = tusUploader.uploadChunk();
                          if (chunkUploaded > 0) {
                              uploadedBytes += chunkUploaded;
                              listener.onUploadPogress(uploadedBytes, totalUploadSize);
                          } else {
                              // upload is complete
                              break;
                          }
                      }
                  }
              };
  
              tusExecutor.makeAttempts();
              if (state != State.UPLOADING) {
                  // if upload is paused, save the uploader so it can be reused on resume, then leave the method early.
                  lastTusUploader = tusUploader;
                  return;
              }
  
              // remove upload instance from list
              uploads.remove(0);
              tusUploader.finish();
          }
  
          setState(State.UPLOAD_COMPLETE);
      }