Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
Tobias Kaminsky 2022-12-13 02:31:01 +01:00
commit eba4cc8404
8 changed files with 148 additions and 99 deletions

View file

@ -78,21 +78,24 @@ class FilesUploadWorker(
return Result.failure() // user account is needed
}
// get all pending uploads
var currentAndPendingUploadsForAccount =
uploadsStorageManager.getCurrentAndPendingUploadsForAccount(MAX_UPLOADS_QUERY, accountName)
while (currentAndPendingUploadsForAccount.isNotEmpty()) {
Log_OC.d(TAG, "Handling ${currentAndPendingUploadsForAccount.size} uploads for account $accountName")
handlePendingUploads(currentAndPendingUploadsForAccount, accountName)
currentAndPendingUploadsForAccount =
uploadsStorageManager.getCurrentAndPendingUploadsForAccount(MAX_UPLOADS_QUERY, accountName)
/*
* As pages are retrieved by sorting uploads by ID, if new uploads are added while uploading the current ones,
* they will be present in the pages that follow.
*/
var currentPage = uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(-1, accountName)
while (currentPage.isNotEmpty()) {
Log_OC.d(TAG, "Handling ${currentPage.size} uploads for account $accountName")
val lastId = currentPage.last().uploadId
handlePendingUploads(currentPage, accountName)
currentPage =
uploadsStorageManager.getCurrentAndPendingUploadsForAccountPageAscById(lastId, accountName)
}
Log_OC.d(TAG, "No more pending uploads for account $accountName, stopping work")
return Result.success()
}
private fun handlePendingUploads(uploads: Array<OCUpload>, accountName: String) {
private fun handlePendingUploads(uploads: List<OCUpload>, accountName: String) {
val user = userAccountManager.getUser(accountName)
for (upload in uploads) {
@ -240,7 +243,6 @@ class FilesUploadWorker(
companion object {
val TAG: String = FilesUploadWorker::class.java.simpleName
private const val MAX_UPLOADS_QUERY = 100
private const val FOREGROUND_SERVICE_ID: Int = 412
private const val MAX_PROGRESS: Int = 100
const val ACCOUNT = "data_account"

View file

@ -56,8 +56,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
/**
* Database helper for storing list of files to be uploaded, including status
* information for each file.
* Database helper for storing list of files to be uploaded, including status information for each file.
*/
public class UploadsStorageManager extends Observable {
private static final String TAG = UploadsStorageManager.class.getSimpleName();
@ -65,13 +64,15 @@ public class UploadsStorageManager extends Observable {
private static final String AND = " AND ";
private static final int SINGLE_RESULT = 1;
private static final long QUERY_PAGE_SIZE = 100;
private final ContentResolver contentResolver;
private final CurrentAccountProvider currentAccountProvider;
public UploadsStorageManager(
CurrentAccountProvider currentAccountProvider,
ContentResolver contentResolver
) {
) {
if (contentResolver == null) {
throw new IllegalArgumentException("Cannot create an instance with a NULL contentResolver");
}
@ -364,77 +365,30 @@ public class UploadsStorageManager extends Observable {
}
private OCUpload[] getUploads(@Nullable String selection, @Nullable String... selectionArgs) {
return getUploads(0, selection, selectionArgs);
}
private OCUpload[] getUploads(final int limit, @Nullable String selection, @Nullable String... selectionArgs) {
ArrayList<OCUpload> uploads = new ArrayList<>();
final long pageSize = 100;
final List<OCUpload> uploads = new ArrayList<>();
long page = 0;
long rowsRead;
long rowsTotal = 0;
long lastRowID = -1;
do {
String pageSelection = selection;
String[] pageSelectionArgs = selectionArgs;
if (page > 0 && lastRowID >= 0) {
if (selection != null) {
pageSelection = "(" + selection + ") AND _id < ?";
} else {
pageSelection = "_id < ?";
}
if (selectionArgs != null) {
pageSelectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
} else {
pageSelectionArgs = new String[1];
}
pageSelectionArgs[pageSelectionArgs.length - 1] = String.valueOf(lastRowID);
Log_OC.d(TAG, String.format(Locale.ENGLISH, "QUERY: %s ROWID: %d", pageSelection, lastRowID));
} else {
Log_OC.d(TAG, String.format(Locale.ENGLISH, "QUERY: %s ROWID: %d", selection, lastRowID));
final List<OCUpload> uploadsPage = getUploadPage(lastRowID, selection, selectionArgs);
rowsRead = uploadsPage.size();
rowsTotal += rowsRead;
if (!uploadsPage.isEmpty()) {
lastRowID = uploadsPage.get(uploadsPage.size() - 1).getUploadId();
}
rowsRead = 0;
Log_OC.v(TAG, String.format(Locale.ENGLISH,
"getUploads() got %d rows from page %d, %d rows total so far, last ID %d",
rowsRead,
page,
rowsTotal,
lastRowID
));
uploads.addAll(uploadsPage);
page++;
} while (rowsRead > 0);
Cursor c = getDB().query(
ProviderTableMeta.CONTENT_URI_UPLOADS,
null,
pageSelection,
pageSelectionArgs,
String.format(Locale.ENGLISH, "_id DESC LIMIT %d", pageSize)
);
if (c != null) {
if (c.moveToFirst()) {
do {
rowsRead++;
rowsTotal++;
lastRowID = c.getLong(c.getColumnIndexOrThrow(ProviderTableMeta._ID));
OCUpload upload = createOCUploadFromCursor(c);
if (upload == null) {
Log_OC.e(TAG, "OCUpload could not be created from cursor");
} else {
uploads.add(upload);
}
} while (c.moveToNext() && !c.isAfterLast());
}
c.close();
Log_OC.v(TAG, String.format(Locale.ENGLISH,
"getUploads() got %d rows from page %d, %d rows total so far, last ID %d",
rowsRead,
page,
rowsTotal,
lastRowID
));
page += 1;
} else {
break;
}
} while (rowsRead > 0 && (limit <= 0 || rowsRead < limit));
if (limit > 0 && uploads.size() > limit) {
uploads = new ArrayList<>(uploads.subList(0, limit));
}
Log_OC.v(TAG, String.format(Locale.ENGLISH,
"getUploads() returning %d (%d) rows after reading %d pages",
@ -447,6 +401,67 @@ public class UploadsStorageManager extends Observable {
return uploads.toArray(new OCUpload[0]);
}
@NonNull
private List<OCUpload> getUploadPage(final long afterId, @Nullable String selection, @Nullable String... selectionArgs) {
return getUploadPage(afterId, true, selection, selectionArgs);
}
@NonNull
private List<OCUpload> getUploadPage(final long afterId, final boolean descending, @Nullable String selection, @Nullable String... selectionArgs) {
List<OCUpload> uploads = new ArrayList<>();
String pageSelection = selection;
String[] pageSelectionArgs = selectionArgs;
String idComparator;
String sortDirection;
if (descending) {
sortDirection = "DESC";
idComparator = "<";
} else {
sortDirection = "ASC";
idComparator = ">";
}
if (afterId >= 0) {
if (selection != null) {
pageSelection = "(" + selection + ") AND _id " + idComparator + " ?";
} else {
pageSelection = "_id " + idComparator + " ?";
}
if (selectionArgs != null) {
pageSelectionArgs = Arrays.copyOf(selectionArgs, selectionArgs.length + 1);
} else {
pageSelectionArgs = new String[1];
}
pageSelectionArgs[pageSelectionArgs.length - 1] = String.valueOf(afterId);
Log_OC.d(TAG, String.format(Locale.ENGLISH, "QUERY: %s ROWID: %d", pageSelection, afterId));
} else {
Log_OC.d(TAG, String.format(Locale.ENGLISH, "QUERY: %s ROWID: %d", selection, afterId));
}
Cursor c = getDB().query(
ProviderTableMeta.CONTENT_URI_UPLOADS,
null,
pageSelection,
pageSelectionArgs,
String.format(Locale.ENGLISH, "_id " + sortDirection + " LIMIT %d", QUERY_PAGE_SIZE)
);
if (c != null) {
if (c.moveToFirst()) {
do {
OCUpload upload = createOCUploadFromCursor(c);
if (upload == null) {
Log_OC.e(TAG, "OCUpload could not be created from cursor");
} else {
uploads.add(upload);
}
} while (c.moveToNext() && !c.isAfterLast());
}
c.close();
}
return uploads;
}
private OCUpload createOCUploadFromCursor(Cursor c) {
OCUpload upload = null;
if (c != null) {
@ -484,11 +499,7 @@ public class UploadsStorageManager extends Observable {
}
public OCUpload[] getCurrentAndPendingUploadsForAccount(final @NonNull String accountName) {
return getCurrentAndPendingUploadsForAccount(0, accountName);
}
public OCUpload[] getCurrentAndPendingUploadsForAccount(final int limit, final @NonNull String accountName) {
return getUploads(limit, ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value +
return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_WIFI.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
@ -501,21 +512,40 @@ public class UploadsStorageManager extends Observable {
accountName);
}
/**
* Gets a page of uploads after <code>afterId</code>, where uploads are sorted by ascending upload id.
* <p>
* If <code>afterId</code> is -1, returns the first page
*/
public List<OCUpload> getCurrentAndPendingUploadsForAccountPageAscById(final long afterId, final @NonNull String accountName) {
final String selection = ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_WIFI.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.LOCK_FAILED.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_CHARGING.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_IN_POWER_SAVE_MODE.getValue() +
" AND " + ProviderTableMeta.UPLOADS_ACCOUNT_NAME + "== ?";
return getUploadPage(afterId, false, selection, accountName);
}
/**
* Get all failed uploads.
*/
public OCUpload[] getFailedUploads() {
return getUploads("(" + ProviderTableMeta.UPLOADS_STATUS + "== ?" +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_WIFI.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.LOCK_FAILED.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_CHARGING.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_IN_POWER_SAVE_MODE.getValue() +
" ) AND " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"!= " + UploadResult.VIRUS_DETECTED.getValue()
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_WIFI.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.LOCK_FAILED.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_FOR_CHARGING.getValue() +
" OR " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"==" + UploadResult.DELAYED_IN_POWER_SAVE_MODE.getValue() +
" ) AND " + ProviderTableMeta.UPLOADS_LAST_RESULT +
"!= " + UploadResult.VIRUS_DETECTED.getValue()
, String.valueOf(UploadStatus.UPLOAD_FAILED.value));
}

View file

@ -109,8 +109,8 @@ class PreviewVideoFullscreenDialog(
if (isPlaying) {
sourceExoPlayer.pause()
}
enableImmersiveMode()
setOnShowListener {
enableImmersiveMode()
switchTargetViewFromSource()
setListeners()
if (isPlaying) {
@ -157,8 +157,8 @@ class PreviewVideoFullscreenDialog(
if (isPlaying) {
mExoPlayer.pause()
}
disableImmersiveMode()
setOnDismissListener {
disableImmersiveMode()
playingStateListener?.let {
mExoPlayer.removeListener(it)
}
@ -180,12 +180,7 @@ class PreviewVideoFullscreenDialog(
}
private fun enableImmersiveMode() {
// for immersive mode to work properly, need to disable statusbar on activity window, but nav bar in dialog
// otherwise dialog navbar is not hidden, or statusbar padding is the wrong color
activity.window?.let {
hideInset(it, WindowInsetsCompat.Type.statusBars())
}
window?.let {
hideInset(it, WindowInsetsCompat.Type.systemBars())
}
}

View file

@ -355,6 +355,7 @@
<string name="local_file_list_empty">No hay archivos en esta carpeta</string>
<string name="local_file_not_found_message">No se encontró el archivo en el sistema de archivos local</string>
<string name="local_folder_list_empty">No hay más carpetas.</string>
<string name="lock_file">Archivo bloqueado</string>
<string name="log_send_mail_subject"> %1$s bitácora de aplicación Android</string>
<string name="login">Iniciar sesión</string>
<string name="logs_menu_delete">Eliminar los registros</string>
@ -569,6 +570,7 @@
<string name="trashbin_empty_message">Podrás recuperar los archivos eliminados desde aquí </string>
<string name="trashbin_file_not_deleted">¡El archivo %1$s no pudo ser eliminado!</string>
<string name="trashbin_not_emptied">¡Los archivos no pudieron ser eliminados permanentemente!</string>
<string name="unlock_file">Archivo desbloqueado</string>
<string name="unset_encrypted">Desestablecer encripción</string>
<string name="unset_favorite">Eliminar de favoritos</string>
<string name="unshare_link_forbidden_permissions">para dejar de compartir este archivo</string>

View file

@ -35,6 +35,7 @@
<string name="add_to_cloud">Gehitu %1$s</string>
<string name="advanced_settings">Ezarpen aurreratuak</string>
<string name="allow_resharing">Baimendu birpartekatzea</string>
<string name="app_widget_description">Arbeleko widget bat erakusten du</string>
<string name="appbar_search_in">Bilatu %s(e)n</string>
<string name="associated_account_not_found">Ez da aurkitu lotutako konturik</string>
<string name="auth_access_failed">Huts egin du atzitzean: %1$s</string>
@ -87,6 +88,7 @@
<string name="calendars">Egutegiak</string>
<string name="certificate_load_problem">Arazo bat dago egiaztagiria kargatzean</string>
<string name="changelog_dev_version">Garapen bertsioaren aldaketa-egunkaria</string>
<string name="check_back_later_or_reload">Begiratu berriro geroago edo kargatu berriro.</string>
<string name="checkbox">Kontrol laukia</string>
<string name="choose_local_folder">Hautatu tokiko karpeta...</string>
<string name="choose_location">Hautatu kokapena</string>
@ -268,6 +270,7 @@
<string name="error_report_issue_text">Arazoaren berri eman nahi duzu? (GitHub kontu bat beharrezkoa da)</string>
<string name="error_retrieving_file">Errorea fitxategia berreskuratzean</string>
<string name="error_retrieving_templates">Errorea txantiloiak berreskuratzean</string>
<string name="error_showing_encryption_dialog">Errore bat gertatu da konfigurazio enkriptatzeko elkarrizketa-koadroa erakustean!</string>
<string name="error_starting_direct_camera_upload">Errorea kamera abiaraztean</string>
<string name="error_starting_scan_doc">Errorea dokumentu eskaneatzailea erabiltzerakoan</string>
<string name="etm_accounts">Kontuak</string>
@ -392,6 +395,9 @@
<string name="hint_password">Pasahitza</string>
<string name="host_not_available">Zerbitzaria ez dago eskuragarri</string>
<string name="host_your_own_server">Ostatatu zure zerbitzaria</string>
<string name="icon_for_empty_list">Zerrenda hutsaren ikonoa</string>
<string name="icon_of_dashboard_widget">Arbeleko widgetaren ikonoa</string>
<string name="icon_of_widget_entry">Widget-sarreraren ikonoa</string>
<string name="in_folder">%1$skarpetan</string>
<string name="instant_upload_existing">Existitzen diren fitxategiak ere kargatu</string>
<string name="instant_upload_on_charging">Igo bakarrik gailua kargatzean</string>
@ -514,6 +520,8 @@
<string name="permission_deny">Ukatu</string>
<string name="permission_storage_access">Fitxategiak kargatu eta deskargatzeko baimen gehigarriak behar dira</string>
<string name="picture_set_as_no_app">Ez da aplikaziorik aurkitu irudia ezartzeko</string>
<string name="pin_home">Ainguratu hasierako pantailan</string>
<string name="pin_shortcut_label">Ireki %1$s</string>
<string name="placeholder_fileSize">389 KB</string>
<string name="placeholder_filename">leku-marka.txt</string>
<string name="placeholder_media_time">12:23:45</string>
@ -543,6 +551,8 @@
<string name="prefs_category_general">Orokorra</string>
<string name="prefs_category_more">Gehiago</string>
<string name="prefs_daily_backup_summary">Eguneroko babeskopia zure egutegi eta kontaktuentzat</string>
<string name="prefs_davx5_setup_error">Ustekabeko errorea DAVx5 konfiguratzean (lehen DAVdroid izenez ezagutzen zena)</string>
<string name="prefs_e2e_active">Muturretik muturrerako enkriptatzea konfiguratuta dago!</string>
<string name="prefs_e2e_mnemonic">E2E mnemoteknikoa</string>
<string name="prefs_e2e_no_device_credentials">Mnemoteknikoa erakusteko, gaitu gailuaren kredentzialak.</string>
<string name="prefs_enable_media_scan_notifications">Erakutsi multimedia azterketen jakinarazpenak</string>
@ -554,6 +564,7 @@
<string name="prefs_instant_behaviour_title">Jatorrizko fitxategia izango da...</string>
<string name="prefs_instant_upload_path_use_subfolders_summary">Biltegiratu urtearen eta hilabetearen araberako azpikarpetetan</string>
<string name="prefs_instant_upload_path_use_subfolders_title">Erabili azpikarpetak</string>
<string name="prefs_keys_exist">Gehitu muturretik muturrerako enkriptatzea bezero honi</string>
<string name="prefs_license">Lizentzia</string>
<string name="prefs_lock">Aplikazio pasahitza</string>
<string name="prefs_lock_device_credentials_enabled">Gailuaren egiaztagiriak gaituta</string>
@ -564,6 +575,8 @@
<string name="prefs_lock_using_passcode">Pasahitza</string>
<string name="prefs_manage_accounts">Kudeatu kontuak</string>
<string name="prefs_recommend">Gomendatu lagun bati</string>
<string name="prefs_remove_e2e">Kendu enkriptatzea lokalean</string>
<string name="prefs_setup_e2e">Konfiguratu muturretik muturrerako enkriptatzea</string>
<string name="prefs_show_hidden_files">Erakutsi ezkutuko fitxategiak</string>
<string name="prefs_sourcecode">Eskuratu iturburu-kodea</string>
<string name="prefs_storage_path">Datu-biltegiratze karpeta</string>
@ -591,6 +604,8 @@
<string name="reload">Birkargatu</string>
<string name="remote">(urrunekoa)</string>
<string name="remote_file_fetch_failed">Fitxategia bilatzeak huts egin du!</string>
<string name="remove_e2e">Lokalean, muturretik muturrerako enkriptatzea ken dezakezu bezero honetan</string>
<string name="remove_e2e_message">Lokalean, muturretik muturrerako enkriptatzea ken dezakezu bezero honetan. Enkriptatutako fitxategiak zerbitzarian jarraituko dute, baina ez dira ordenagailu honekin sinkronizatuko.</string>
<string name="remove_fail_msg">Ezabatzeak huts egin du</string>
<string name="remove_notification_failed">Huts egin du jakinarazpena kentzean</string>
<string name="remove_push_notification">Ezabatu</string>
@ -634,6 +649,7 @@
<string name="set_picture_as">Erabili irudia honela</string>
<string name="set_status">Ezarri egoera</string>
<string name="set_status_message">Ezarri egoera mezua</string>
<string name="setup_e2e">Muturretik muturrerako enkriptatzea konfiguratzean, ausazko 12 hitz mnemoteknikoa jasoko duzu, zure fitxategiak beste gailu batzuetan ireki beharko dituzunak. Gailu horretan bakarrik gordeko da eta pantaila honetan berriro erakutsi ahal izango da. Apuntatu leku seguru batean!</string>
<string name="share">Partekatu</string>
<string name="share_copy_link">Partekatu eta kopiatu esteka</string>
<string name="share_dialog_title">Partekatzea</string>
@ -879,6 +895,7 @@
<string name="userinfo_no_info_text">Gehitu izena, irudia eta kontaktuko zehaztasunak zure profilaren orrian</string>
<string name="username">Erabiltzaile-izena</string>
<string name="version_dev_download">Deskargatu</string>
<string name="video_overlay_icon">Bideoa gainjartzeko ikonoa</string>
<string name="wait_a_moment">Itxaron momentu bat…</string>
<string name="wait_checking_credentials">Gordetako nortasun-datuak konprobatzen</string>
<string name="wait_for_tmp_copy_from_private_storage">Fitxategia biltegiratze pribatutik kopiatzen</string>
@ -886,6 +903,7 @@
<string name="whats_new_skip">Salto egin</string>
<string name="whats_new_title">Berria %1$s-n</string>
<string name="whats_your_status">Zein da zure egoera?</string>
<string name="widgets_not_available">Widgetak %1$s 25 edo geroago bakarrik daude eskuragarri</string>
<string name="widgets_not_available_title">Ez dago erabilgarri</string>
<string name="write_email">Bidali e-posta</string>
<string name="wrong_storage_path">Datu-biltegiratze karpeta ez dago!</string>

View file

@ -435,6 +435,7 @@ Otomatis unggah hanya bekerja dengan baik apabila anda mengeluarkan aplikasi ini
<string name="prefs_sourcecode">Dapatkan kode sumber</string>
<string name="prefs_synced_folders_local_path_title">Berkas lokal</string>
<string name="prefs_synced_folders_remote_path_title">Folder remot</string>
<string name="prefs_theme_title">Tema</string>
<string name="prefs_value_theme_dark">Gelap</string>
<string name="prefs_value_theme_light">Terang</string>
<string name="preview_image_description">Pratilik gambar</string>

View file

@ -551,6 +551,7 @@
<string name="prefs_category_general">Ogólne</string>
<string name="prefs_category_more">Więcej</string>
<string name="prefs_daily_backup_summary">Codzienna kopia zapasowa kontaktów i kalendarza</string>
<string name="prefs_davx5_setup_error">Nieoczekiwany błąd podczas konfigurowania DAVx5 (wcześniej znanego jako DAVdroid)</string>
<string name="prefs_e2e_active">Szyfrowanie end-to-end jest skonfigurowane!</string>
<string name="prefs_e2e_mnemonic">Mnemonik E2E</string>
<string name="prefs_e2e_no_device_credentials">Aby pokazać mnemonik włącz poświadczenia urządzenia.</string>

View file

@ -221,7 +221,7 @@
<string name="downloader_not_downloaded_yet">Ще не завантажене</string>
<string name="drawer_close">Закрити бічну панель</string>
<string name="drawer_community">Спільнота</string>
<string name="drawer_header_background">Фонове зображення заголовку скрині</string>
<string name="drawer_header_background">Зображення тла верхньої панелі</string>
<string name="drawer_item_activities">Події</string>
<string name="drawer_item_all_files">Усі файли</string>
<string name="drawer_item_favorites">Із зірочкою</string>