├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug-report.md
│ ├── config.yml
│ └── feature-request.md
└── workflows
│ ├── android.yml
│ ├── dependencies.yml
│ ├── lint.yml
│ └── translations.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── LICENSE_rcloneExplorer-1.7.4
├── README.md
├── SECURITY.md
├── app
├── .gitignore
├── build.gradle
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── changelog.md
│ │ └── contributors.md
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ ├── ca
│ │ │ └── pkay
│ │ │ │ └── rcloneexplorer
│ │ │ │ ├── Activities
│ │ │ │ ├── AboutActivity.java
│ │ │ │ ├── AboutLibsActivity.java
│ │ │ │ ├── ChangelogActivity.java
│ │ │ │ ├── ContributorActivity.java
│ │ │ │ ├── FilterActivity.kt
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── OnboardingActivity.kt
│ │ │ │ ├── SettingsActivity.java
│ │ │ │ ├── SharingActivity.java
│ │ │ │ ├── ShortcutServiceActivity.kt
│ │ │ │ ├── TaskActivity.kt
│ │ │ │ └── TriggerActivity.kt
│ │ │ │ ├── AppShortcutsHelper.java
│ │ │ │ ├── BroadcastReceivers
│ │ │ │ ├── BootReciever.java
│ │ │ │ ├── ClearReportBroadcastReciever.kt
│ │ │ │ ├── ServeCancelAction.java
│ │ │ │ ├── SyncRestartAction.java
│ │ │ │ └── TriggerReciever.java
│ │ │ │ ├── Database
│ │ │ │ ├── DatabaseHandler.kt
│ │ │ │ ├── DatabaseInfo.kt
│ │ │ │ └── json
│ │ │ │ │ ├── Exporter.java
│ │ │ │ │ ├── Importer.java
│ │ │ │ │ └── SharedPreferencesBackup.java
│ │ │ │ ├── Dialogs
│ │ │ │ ├── Dialogs.java
│ │ │ │ ├── FilePropertiesDialog.java
│ │ │ │ ├── GoToDialog.java
│ │ │ │ ├── InputDialog.java
│ │ │ │ ├── LinkDialog.java
│ │ │ │ ├── LoadingDialog.java
│ │ │ │ ├── NumberPickerDialog.java
│ │ │ │ ├── OpenAsDialog.java
│ │ │ │ ├── PasswordGeneratorDialog.java
│ │ │ │ ├── RemoteDestinationDialog.java
│ │ │ │ ├── RemotePropertiesDialog.java
│ │ │ │ ├── ServeDialog.java
│ │ │ │ └── SortDialog.java
│ │ │ │ ├── FileComparators.java
│ │ │ │ ├── FilePicker.java
│ │ │ │ ├── Fragments
│ │ │ │ ├── FileExplorerFragment.java
│ │ │ │ ├── FolderSelectorCallback.java
│ │ │ │ ├── LogFragment.java
│ │ │ │ ├── PermissionFragment.kt
│ │ │ │ ├── RemoteFolderPickerFragment.java
│ │ │ │ ├── RemotesFragment.java
│ │ │ │ ├── ShareFragment.java
│ │ │ │ ├── ShareRemotesFragment.java
│ │ │ │ ├── TasksFragment.java
│ │ │ │ └── TriggerFragment.java
│ │ │ │ ├── InteractiveRunner.java
│ │ │ │ ├── Items
│ │ │ │ ├── DirectoryObject.java
│ │ │ │ ├── FileItem.java
│ │ │ │ ├── Filter.kt
│ │ │ │ ├── FilterEntry.java
│ │ │ │ ├── RemoteItem.java
│ │ │ │ ├── SyncDirectionObject.java
│ │ │ │ ├── Task.kt
│ │ │ │ └── Trigger.kt
│ │ │ │ ├── Log2File.java
│ │ │ │ ├── Rclone.java
│ │ │ │ ├── RcloneRcd.java
│ │ │ │ ├── RecyclerViewAdapters
│ │ │ │ ├── AboutLibrariesAdapter.java
│ │ │ │ ├── FileExplorerRecyclerViewAdapter.java
│ │ │ │ ├── FilePickerAdapter.java
│ │ │ │ ├── FilterEntryRecyclerViewAdapter.java
│ │ │ │ ├── LogRecyclerViewAdapter.java
│ │ │ │ ├── RemoteConfigListItemAdapter.kt
│ │ │ │ ├── RemotesRecyclerViewAdapter.java
│ │ │ │ ├── ShareRemotesRecyclerViewAdapter.java
│ │ │ │ ├── TasksRecyclerViewAdapter.java
│ │ │ │ └── TriggerRecyclerViewAdapter.java
│ │ │ │ ├── RemoteConfig
│ │ │ │ ├── ConfigCreate.kt
│ │ │ │ ├── DynamicRemoteConfigFragment.kt
│ │ │ │ ├── OauthHelper.java
│ │ │ │ ├── ProviderListFragment.kt
│ │ │ │ ├── RemoteConfig.kt
│ │ │ │ └── RemoteConfigHelper.java
│ │ │ │ ├── RuntimeConfiguration.java
│ │ │ │ ├── Services
│ │ │ │ ├── RcdService.java
│ │ │ │ ├── StreamingService.java
│ │ │ │ ├── SyncService.kt
│ │ │ │ ├── ThumbnailsLoadingService.java
│ │ │ │ └── TriggerService.java
│ │ │ │ ├── Settings
│ │ │ │ ├── FileAccessPreferencesFragment.kt
│ │ │ │ ├── FileAccessSettingsFragment.java
│ │ │ │ ├── GeneralPreferencesFragment.kt
│ │ │ │ ├── LogPreferencesFragment.kt
│ │ │ │ ├── NotificationPreferencesFragment.kt
│ │ │ │ ├── SettingsFragment.java
│ │ │ │ └── ThemingPreferencesFragment.kt
│ │ │ │ ├── SpinnerAdapters
│ │ │ │ └── FilterSpinnerAdapter.kt
│ │ │ │ ├── VirtualContentProvider.java
│ │ │ │ ├── notifications
│ │ │ │ ├── AppErrorNotificationManager.kt
│ │ │ │ ├── GenericSyncNotification.kt
│ │ │ │ ├── ReportNotifications.kt
│ │ │ │ ├── SyncServiceNotifications.kt
│ │ │ │ ├── prototypes
│ │ │ │ │ └── WorkerNotification.kt
│ │ │ │ └── support
│ │ │ │ │ ├── ErrorObject.kt
│ │ │ │ │ ├── GenericNotification.kt
│ │ │ │ │ └── StatusObject.kt
│ │ │ │ ├── rclone
│ │ │ │ ├── OptionExampleItem.kt
│ │ │ │ ├── Provider.kt
│ │ │ │ └── ProviderOption.kt
│ │ │ │ ├── util
│ │ │ │ ├── ActivityHelper.java
│ │ │ │ ├── FLog.java
│ │ │ │ ├── FlagsUtil.kt
│ │ │ │ ├── LargeParcel.java
│ │ │ │ ├── MarkdownView.java
│ │ │ │ ├── NotificationUtils.kt
│ │ │ │ ├── PermissionManager.kt
│ │ │ │ ├── Rfc3339Deserializer.java
│ │ │ │ ├── SharedPreferencesUtil.kt
│ │ │ │ ├── SyncLog.java
│ │ │ │ └── WifiConnectivitiyUtil.kt
│ │ │ │ └── workmanager
│ │ │ │ ├── EphemeralTaskManager.kt
│ │ │ │ ├── EphemeralWorker.kt
│ │ │ │ ├── SyncManager.kt
│ │ │ │ ├── SyncWorker.kt
│ │ │ │ └── Type.kt
│ │ └── de
│ │ │ └── felixnuesse
│ │ │ ├── extract
│ │ │ ├── extensions
│ │ │ │ └── TAG.kt
│ │ │ ├── notifications
│ │ │ │ ├── AppUpdateNotification.kt
│ │ │ │ ├── DiscardChannels.kt
│ │ │ │ └── implementations
│ │ │ │ │ ├── DeleteWorkerNotification.kt
│ │ │ │ │ ├── DownloadWorkerNotification.kt
│ │ │ │ │ ├── MoveWorkerNotification.kt
│ │ │ │ │ └── UploadWorkerNotification.kt
│ │ │ ├── onboarding
│ │ │ │ ├── IdentifiableAppIntroFragment.kt
│ │ │ │ ├── IdentifiableSwitchAppIntroFragment.kt
│ │ │ │ ├── SlideLeaveInterface.kt
│ │ │ │ └── SlideSwitchCallback.kt
│ │ │ ├── settings
│ │ │ │ ├── language
│ │ │ │ │ ├── LanguagePicker.kt
│ │ │ │ │ └── LocaleAdapter.kt
│ │ │ │ └── preferences
│ │ │ │ │ ├── ButtonPreference.kt
│ │ │ │ │ ├── EditIntPreference.kt
│ │ │ │ │ ├── FilesizePreference.kt
│ │ │ │ │ └── dialogs
│ │ │ │ │ └── FilesizeDialog.kt
│ │ │ └── updates
│ │ │ │ ├── UpdateChecker.kt
│ │ │ │ ├── UpdateUserchoiceReceiver.kt
│ │ │ │ └── workmanager
│ │ │ │ ├── UpdateManager.kt
│ │ │ │ └── UpdateWorker.kt
│ │ │ └── ui
│ │ │ ├── BreadcrumbView.kt
│ │ │ └── CrumbView.kt
│ └── res
│ │ ├── anim
│ │ ├── fade_in_animation.xml
│ │ └── fade_out_animation.xml
│ │ ├── drawable
│ │ ├── appicon.xml
│ │ ├── ic_add.xml
│ │ ├── ic_amazon.xml
│ │ ├── ic_amazon_foreground.xml
│ │ ├── ic_arrow_back.xml
│ │ ├── ic_arrow_right.xml
│ │ ├── ic_azure_storage_blob_logo.xml
│ │ ├── ic_backblaze_b2_black.xml
│ │ ├── ic_baseline_stop_24.xml
│ │ ├── ic_box.xml
│ │ ├── ic_box_foreground.xml
│ │ ├── ic_bug_report.xml
│ │ ├── ic_cancel.xml
│ │ ├── ic_cancel_download.xml
│ │ ├── ic_cancel_white.xml
│ │ ├── ic_changelog.xml
│ │ ├── ic_check.xml
│ │ ├── ic_circle.xml
│ │ ├── ic_close.xml
│ │ ├── ic_cloud.xml
│ │ ├── ic_cloud_download_black_24dp.xml
│ │ ├── ic_cloud_foreground.xml
│ │ ├── ic_contributor.xml
│ │ ├── ic_create_new_folder.xml
│ │ ├── ic_delete.xml
│ │ ├── ic_delete_black.xml
│ │ ├── ic_dino2.xml
│ │ ├── ic_drive_foreground.xml
│ │ ├── ic_dropbox.xml
│ │ ├── ic_dropbox_foreground.xml
│ │ ├── ic_edit.xml
│ │ ├── ic_edit_black.xml
│ │ ├── ic_empty_box.xml
│ │ ├── ic_export.xml
│ │ ├── ic_file.xml
│ │ ├── ic_file_alert.xml
│ │ ├── ic_file_black.xml
│ │ ├── ic_file_download.xml
│ │ ├── ic_file_upload.xml
│ │ ├── ic_folder.xml
│ │ ├── ic_folder_move.xml
│ │ ├── ic_folder_open.xml
│ │ ├── ic_google.xml
│ │ ├── ic_google_drive.xml
│ │ ├── ic_google_foreground.xml
│ │ ├── ic_google_photos.xml
│ │ ├── ic_heart_red_24dp.xml
│ │ ├── ic_home.xml
│ │ ├── ic_import.xml
│ │ ├── ic_info_outline.xml
│ │ ├── ic_intro_notifications.xml
│ │ ├── ic_intro_storage.png
│ │ ├── ic_koofr.xml
│ │ ├── ic_launcher_background_debug.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_launcher_foreground_debug.xml
│ │ ├── ic_libraries.xml
│ │ ├── ic_local_foreground.xml
│ │ ├── ic_lock.xml
│ │ ├── ic_lock_black.xml
│ │ ├── ic_lock_foreground.xml
│ │ ├── ic_look_and_feel.xml
│ │ ├── ic_mark_github.xml
│ │ ├── ic_mega_logo_black.xml
│ │ ├── ic_menu.xml
│ │ ├── ic_more_vert.xml
│ │ ├── ic_notifications.xml
│ │ ├── ic_onedrive.xml
│ │ ├── ic_onedrive_foreground.xml
│ │ ├── ic_open_drive.xml
│ │ ├── ic_pcloud.xml
│ │ ├── ic_person_outline.xml
│ │ ├── ic_pin.xml
│ │ ├── ic_pound.xml
│ │ ├── ic_rclone_logo.xml
│ │ ├── ic_refresh.xml
│ │ ├── ic_round_av_timer_24.xml
│ │ ├── ic_round_list_24.xml
│ │ ├── ic_round_swap_vert_24.xml
│ │ ├── ic_sd_storage.xml
│ │ ├── ic_search.xml
│ │ ├── ic_search_black_24dp.xml
│ │ ├── ic_select_all.xml
│ │ ├── ic_settings.xml
│ │ ├── ic_sort.xml
│ │ ├── ic_streaming.xml
│ │ ├── ic_tablet_cellphone.xml
│ │ ├── ic_terminal.xml
│ │ ├── ic_terminal_foreground.xml
│ │ ├── ic_twotone_cancel_24.xml
│ │ ├── ic_twotone_check_circle_24.xml
│ │ ├── ic_twotone_cloud_24.xml
│ │ ├── ic_twotone_cloud_done_24.xml
│ │ ├── ic_twotone_cloud_download_24.xml
│ │ ├── ic_twotone_cloud_error_24.xml
│ │ ├── ic_twotone_cloud_upload_24.xml
│ │ ├── ic_twotone_error_24.xml
│ │ ├── ic_twotone_info_24.xml
│ │ ├── ic_twotone_rounded_cloud_sync_24.xml
│ │ ├── ic_twotone_save_24.xml
│ │ ├── ic_twotone_settings_24.xml
│ │ ├── ic_union_24dp.xml
│ │ ├── ic_webdav.xml
│ │ ├── ic_yandex_mono.xml
│ │ ├── nav_header_background_rounded.xml
│ │ ├── nav_item_background_rounded.xml
│ │ ├── nav_item_color_state.xml
│ │ ├── nav_item_textcolor_state.xml
│ │ ├── pill.xml
│ │ ├── shape_circle.xml
│ │ ├── twotone_home_24.xml
│ │ ├── undraw_completion.xml
│ │ ├── undraw_electricity.xml
│ │ ├── undraw_hello.xml
│ │ ├── undraw_post_online.xml
│ │ ├── undraw_sync.xml
│ │ ├── undraw_the_world_is_mine.xml
│ │ ├── undraw_time_management.xml
│ │ └── undraw_update.xml
│ │ ├── layout-sw720dp
│ │ ├── activity_about.xml
│ │ ├── activity_changelog.xml
│ │ ├── app_bar_main.xml
│ │ ├── content_about_libs.xml
│ │ ├── dialog_remote_dest.xml
│ │ ├── file_picker_list.xml
│ │ ├── fragment_config_list.xml
│ │ ├── fragment_file_explorer_list.xml
│ │ ├── fragment_share_list.xml
│ │ └── remote_config_form.xml
│ │ ├── layout
│ │ ├── about_icon_item.xml
│ │ ├── about_libraries_item.xml
│ │ ├── activity_about.xml
│ │ ├── activity_about_libs.xml
│ │ ├── activity_changelog.xml
│ │ ├── activity_contributors.xml
│ │ ├── activity_file_picker.xml
│ │ ├── activity_filter.xml
│ │ ├── activity_main.xml
│ │ ├── activity_remote_config.xml
│ │ ├── activity_settings.xml
│ │ ├── activity_sharing.xml
│ │ ├── activity_task.xml
│ │ ├── activity_trigger.xml
│ │ ├── app_bar_main.xml
│ │ ├── appintro_fragment_intro_switch.xml
│ │ ├── auth_screen.xml
│ │ ├── bottom_bar.xml
│ │ ├── config_list_item_template.xml
│ │ ├── content_about.xml
│ │ ├── content_about_libs.xml
│ │ ├── content_changelog.xml
│ │ ├── content_contributors.xml
│ │ ├── content_filter.xml
│ │ ├── content_main.xml
│ │ ├── content_remote_config.xml
│ │ ├── content_settings.xml
│ │ ├── content_sharing.xml
│ │ ├── content_task.xml
│ │ ├── content_trigger.xml
│ │ ├── customui_breadcrumbview.xml
│ │ ├── customui_crumbview.xml
│ │ ├── dialog_file_properties.xml
│ │ ├── dialog_go_to.xml
│ │ ├── dialog_input.xml
│ │ ├── dialog_link.xml
│ │ ├── dialog_loading_indicator.xml
│ │ ├── dialog_number_picker.xml
│ │ ├── dialog_open_as.xml
│ │ ├── dialog_password_generator.xml
│ │ ├── dialog_remote_dest.xml
│ │ ├── dialog_remote_properties.xml
│ │ ├── dialog_serve.xml
│ │ ├── dialog_sort.xml
│ │ ├── empty_directory_state.xml
│ │ ├── empty_state_config_file.xml
│ │ ├── file_picker_item.xml
│ │ ├── file_picker_list.xml
│ │ ├── fragment_config_list.xml
│ │ ├── fragment_file_explorer_item.xml
│ │ ├── fragment_file_explorer_list.xml
│ │ ├── fragment_filter_item.xml
│ │ ├── fragment_log_item.xml
│ │ ├── fragment_logs.xml
│ │ ├── fragment_permission_item.xml
│ │ ├── fragment_permissions.xml
│ │ ├── fragment_remote_folder_picker_list.xml
│ │ ├── fragment_remotes_item.xml
│ │ ├── fragment_remotes_list.xml
│ │ ├── fragment_share_list.xml
│ │ ├── fragment_share_remotes_item.xml
│ │ ├── fragment_share_remotes_list.xml
│ │ ├── fragment_tasks.xml
│ │ ├── fragment_tasks_item.xml
│ │ ├── fragment_trigger.xml
│ │ ├── fragment_trigger_item_interval.xml
│ │ ├── fragment_trigger_item_schedule.xml
│ │ ├── locked_config.xml
│ │ ├── move_bar.xml
│ │ ├── nav_header_main.xml
│ │ ├── no_search_results.xml
│ │ ├── preference_button.xml
│ │ ├── preference_filesize.xml
│ │ ├── remote_config_form.xml
│ │ ├── settings_fragment.xml
│ │ ├── settings_fragment_file_access_settings.xml
│ │ ├── settings_fragment_general.xml
│ │ └── spinner_dropdown_item.xml
│ │ ├── menu
│ │ ├── activity_main_drawer.xml
│ │ ├── file_explorer_folder_menu.xml
│ │ ├── file_explorer_menu.xml
│ │ ├── file_picker_menu.xml
│ │ ├── filter_item_menu.xml
│ │ ├── fragment_config_menu.xml
│ │ ├── fragment_share_menu.xml
│ │ ├── remote_config_menu.xml
│ │ ├── remote_folder_picker_menu.xml
│ │ ├── remote_fragment_menu.xml
│ │ ├── remote_options.xml
│ │ ├── task_item_menu.xml
│ │ └── trigger_item_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ ├── ic_launcher_debug.xml
│ │ ├── ic_launcher_debug_round.xml
│ │ ├── ic_launcher_round.xml
│ │ ├── ic_shortcut_amazon.xml
│ │ ├── ic_shortcut_box.xml
│ │ ├── ic_shortcut_cloud.xml
│ │ ├── ic_shortcut_drive.xml
│ │ ├── ic_shortcut_dropbox.xml
│ │ ├── ic_shortcut_google.xml
│ │ ├── ic_shortcut_local.xml
│ │ ├── ic_shortcut_lock.xml
│ │ ├── ic_shortcut_onedrive.xml
│ │ └── ic_shortcut_terminal.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_shortcut_amazon.png
│ │ ├── ic_shortcut_box.png
│ │ ├── ic_shortcut_cloud.png
│ │ ├── ic_shortcut_drive.png
│ │ ├── ic_shortcut_dropbox.png
│ │ ├── ic_shortcut_google.png
│ │ ├── ic_shortcut_local.png
│ │ ├── ic_shortcut_lock.png
│ │ ├── ic_shortcut_onedrive.png
│ │ └── ic_shortcut_terminal.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_shortcut_amazon.png
│ │ ├── ic_shortcut_box.png
│ │ ├── ic_shortcut_cloud.png
│ │ ├── ic_shortcut_drive.png
│ │ ├── ic_shortcut_dropbox.png
│ │ ├── ic_shortcut_google.png
│ │ ├── ic_shortcut_local.png
│ │ ├── ic_shortcut_lock.png
│ │ ├── ic_shortcut_onedrive.png
│ │ └── ic_shortcut_terminal.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_shortcut_amazon.png
│ │ ├── ic_shortcut_box.png
│ │ ├── ic_shortcut_cloud.png
│ │ ├── ic_shortcut_drive.png
│ │ ├── ic_shortcut_dropbox.png
│ │ ├── ic_shortcut_google.png
│ │ ├── ic_shortcut_local.png
│ │ ├── ic_shortcut_lock.png
│ │ ├── ic_shortcut_onedrive.png
│ │ └── ic_shortcut_terminal.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_shortcut_amazon.png
│ │ ├── ic_shortcut_box.png
│ │ ├── ic_shortcut_cloud.png
│ │ ├── ic_shortcut_drive.png
│ │ ├── ic_shortcut_dropbox.png
│ │ ├── ic_shortcut_google.png
│ │ ├── ic_shortcut_local.png
│ │ ├── ic_shortcut_lock.png
│ │ ├── ic_shortcut_onedrive.png
│ │ └── ic_shortcut_terminal.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ ├── ic_shortcut_amazon.png
│ │ ├── ic_shortcut_box.png
│ │ ├── ic_shortcut_cloud.png
│ │ ├── ic_shortcut_drive.png
│ │ ├── ic_shortcut_dropbox.png
│ │ ├── ic_shortcut_google.png
│ │ ├── ic_shortcut_local.png
│ │ ├── ic_shortcut_lock.png
│ │ ├── ic_shortcut_onedrive.png
│ │ └── ic_shortcut_terminal.png
│ │ ├── resources.properties
│ │ ├── values-de
│ │ └── strings.xml
│ │ ├── values-night-v31
│ │ └── colors.xml
│ │ ├── values-night
│ │ ├── styles.xml
│ │ └── themes.xml
│ │ ├── values-sw720dp
│ │ └── isTabletMode.xml
│ │ ├── values-v31
│ │ ├── colors.xml
│ │ └── styles.xml
│ │ ├── values-zh-rCN
│ │ └── strings.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── defaults.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_shortcut_background.xml
│ │ ├── ids.xml
│ │ ├── isTabletMode.xml
│ │ ├── prefkeys.xml
│ │ ├── strings.xml
│ │ ├── styles.xml
│ │ ├── sync_direction_array.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── file_provider_paths.xml
│ │ ├── network_security_config.xml
│ │ ├── paths.xml
│ │ ├── settings_fileaccess_preferences.xml
│ │ ├── settings_general_preferences.xml
│ │ ├── settings_logging_preferences.xml
│ │ ├── settings_notification_preferences.xml
│ │ ├── settings_theming_preferences.xml
│ │ └── virtual_content_provider_paths.xml
│ ├── rcx
│ └── java
│ │ └── ca
│ │ └── pkay
│ │ └── rcloneexplorer
│ │ └── util
│ │ └── CrashLogger.java
│ └── test
│ └── java
│ └── ca
│ └── pkay
│ └── rcloneexplorer
│ ├── ExampleUnitTest.java
│ └── VirtualContentProviderTest.java
├── build.gradle
├── crowdin.yml
├── docs
├── cloud-computing.png
├── locked-padlock.png
└── smartphone.png
├── fastlane
└── metadata
│ └── android
│ └── en-US
│ ├── full_description.txt
│ ├── images
│ ├── featureGraphic.jpg
│ ├── icon.png
│ └── phoneScreenshots
│ │ ├── 1.jpg
│ │ ├── 2.jpg
│ │ ├── 3.jpg
│ │ └── 4.jpg
│ ├── short_description.txt
│ └── title.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── rclone
├── .gitignore
└── build.gradle
├── safdav
├── .gitignore
├── build.gradle
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── io
│ │ └── github
│ │ └── x0b
│ │ └── safdav
│ │ ├── SafAccessProvider.java
│ │ ├── SafDAVServer.java
│ │ ├── SafDirectServer.java
│ │ ├── file
│ │ ├── FileAccessError.java
│ │ ├── ItemAccess.java
│ │ ├── ItemExistsException.java
│ │ ├── ItemNotFoundException.java
│ │ ├── SafConstants.java
│ │ ├── SafException.java
│ │ └── SafItem.java
│ │ ├── package-info.java
│ │ ├── provider
│ │ └── SingleRootProvider.java
│ │ ├── saf
│ │ ├── DocumentsContractAccess.java
│ │ ├── ProviderPaths.java
│ │ ├── SafFastItem.java
│ │ ├── SafFileAccess.java
│ │ ├── SafFileItem.java
│ │ └── SafPermissionItem.java
│ │ └── xml
│ │ └── XmlResponseSerialization.java
│ └── res
│ └── values
│ └── strings.xml
├── scripts
├── checkProfanity.py
└── generateFilelist.sh
└── settings.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: newhinton
4 | custom: ["https://www.paypal.com/paypalme/felixnuesse"]
5 | liberapay: newhinton
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Rclone Forum
4 | url: https://forum.rclone.org/
5 | about: For questions around rclone itself.
6 | - name: Rclone Issue Tracker
7 | url: https://github.com/rclone/rclone/issues
8 | about: When you are sure rclone does not work correctly.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a new feature or enhancement for Round Sync
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ---
11 | **If this is your first feature request, read our [contribution guidelines](../blob/master/CONTRIBUTING.md#requesting-a-new-feature).**
12 |
13 | ---
14 |
15 | #### Pre-Submission checklist
16 |
17 |
18 | - [ ] There is no existing issue that already asks for this feature.
19 | - [ ] The feature already exists in rclone (on your PC or in Termux)
20 | - [ ] I am prepared to help make this feature
21 |
22 | #### What version of Round Sync are you using (About -> App version)?
23 |
24 |
25 |
26 | #### What problem are you trying to solve?
27 |
28 |
29 |
30 | #### What should Round Sync be able to do differently to help with this problem?
31 |
32 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Android Lint
2 |
3 | on:
4 | push:
5 | pull_request:
6 | branches-ignore:
7 | - 'master'
8 |
9 | jobs:
10 | checkLint:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | - name: Set up JDK 17
15 | uses: actions/setup-java@v3
16 | with:
17 | java-version: '17'
18 | distribution: 'temurin'
19 | cache: gradle
20 | - name: Run Linter
21 | run: ./gradlew lint -x :rclone:buildAll
22 | - name: Upload Reports
23 | if: always()
24 | uses: actions/upload-artifact@v4
25 | with:
26 | name: Lint Reports
27 | path: ~/**/build/reports/
28 | retention-days: 30
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/assetWizardSettings.xml
38 | .idea/workspace.xml
39 | .idea/tasks.xml
40 | .idea/gradle.xml
41 | .idea/dictionaries
42 | .idea/libraries
43 | .idea/caches
44 |
45 | # Keystore files
46 | *.jks
47 |
48 | # External native build folder generated in Android Studio 2.2 and later
49 | .externalNativeBuild
50 |
51 | # Google Services (e.g. APIs or Firebase)
52 | google-services.json
53 |
54 | # Freeline
55 | freeline.py
56 | freeline/
57 | freeline_project_description.json
58 |
59 | # Don't version native libraries or IDE artifacts. Module config should be done in gradle.
60 | # Generated artifacts (apks, libraries) just slow down cloning and can be recreated from source
61 | # anyways.
62 | release/
63 | debug/
64 |
65 | .idea/encodings.xml
66 | .idea/caches/build_file_checksums.ser
67 | .idea/misc.xml
68 | .idea/modules.xml
69 | .idea/codeStyles/Project.xml
70 | .idea/codeStyles/codeStyleConfig.xml
71 | .idea/inspectionProfiles/Project_Default.xml
72 | .idea/
73 |
--------------------------------------------------------------------------------
/LICENSE_rcloneExplorer-1.7.4:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Patryk Kaczmarkiewicz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /lib
3 |
--------------------------------------------------------------------------------
/app/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | # don't change names - this is open source anyways, and the biggest size
24 | # contributor are native libs which we can't shrink.
25 | -dontobfuscate
26 |
27 | # ignore okhttp conscrypt warning
28 | -dontwarn okhttp3.internal.platform.ConscryptPlatform
29 |
30 | # keep model classes
31 | # -keep public class ca.pkay.rcloneexplorer.RcloneRcd.*
32 | -keep class ca.pkay.rcloneexplorer.** { *; }
33 |
34 |
35 | -dontwarn org.bouncycastle.jsse.BCSSLParameters
36 | -dontwarn org.bouncycastle.jsse.BCSSLSocket
37 | -dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
38 | -dontwarn org.conscrypt.Conscrypt$Version
39 | -dontwarn org.conscrypt.Conscrypt
40 | -dontwarn org.conscrypt.ConscryptHostnameVerifier
41 | -dontwarn org.openjsse.javax.net.ssl.SSLParameters
42 | -dontwarn org.openjsse.javax.net.ssl.SSLSocket
43 | -dontwarn org.openjsse.net.ssl.OpenJSSE
44 |
--------------------------------------------------------------------------------
/app/src/main/assets/contributors.md:
--------------------------------------------------------------------------------
1 | ### Intro
2 | This application was created by [Patryk Kaczmarkiewicz](https://github.com/kaczmarkiewiczp). Your current build is maintained by [x0b](https://github.com/x0b).
3 |
4 | ### Github contributors
5 | Additionally, these people have contributed towards making RCX better:
6 |
7 | * [buywetwok](https://github.com/buywetwok)
8 | * [davsinghm](https://github.com/davsinghm)
9 | * [alyssadev](https://github.com/alyssadev)
10 |
11 | [Join us now on Github.](https://github.com/x0b/rcx)
12 |
13 | ## License
14 |
15 | Copyright (C) 2018-2020 x0b
16 |
17 | This program is free software: you can redistribute it and/or modify
18 | it under the terms of the GNU General Public License as published by
19 | the Free Software Foundation, either version 3 of the License, or
20 | (at your option) any later version.
21 |
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
26 |
27 | You should have received a copy of the GNU General Public License
28 | along with this program. If not, see .
29 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/newhinton/Round-Sync/56d446a9a57854b51e087dfa0da63f65641eb712/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Activities/ChangelogActivity.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Activities;
2 |
3 | import android.os.Bundle;
4 | import androidx.appcompat.app.ActionBar;
5 | import androidx.appcompat.app.AppCompatActivity;
6 | import androidx.appcompat.widget.Toolbar;
7 |
8 | import ca.pkay.rcloneexplorer.util.ActivityHelper;
9 | import ca.pkay.rcloneexplorer.R;
10 | import ca.pkay.rcloneexplorer.util.MarkdownView;
11 |
12 | public class ChangelogActivity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | ActivityHelper.applyTheme(this);
18 | try {
19 | setContentView(R.layout.activity_changelog);
20 | } catch (Exception e) {
21 | MarkdownView.closeOnMissingWebView(this, e);
22 | }
23 | Toolbar toolbar = findViewById(R.id.toolbar);
24 | setSupportActionBar(toolbar);
25 | ActionBar actionBar = getSupportActionBar();
26 | if (actionBar != null) {
27 | actionBar.setDisplayHomeAsUpEnabled(true);
28 | actionBar.setDisplayShowHomeEnabled(true);
29 | }
30 |
31 | MarkdownView markdownView = findViewById(R.id.markdownView);
32 | markdownView.loadAsset("changelog.md");
33 | }
34 |
35 | @Override
36 | public boolean onSupportNavigateUp() {
37 | onBackPressed();
38 | return true;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Activities/ContributorActivity.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Activities;
2 |
3 | import android.os.Bundle;
4 | import androidx.appcompat.app.ActionBar;
5 | import androidx.appcompat.app.AppCompatActivity;
6 | import androidx.appcompat.widget.Toolbar;
7 |
8 | import ca.pkay.rcloneexplorer.util.ActivityHelper;
9 | import ca.pkay.rcloneexplorer.R;
10 | import ca.pkay.rcloneexplorer.util.MarkdownView;
11 |
12 |
13 | public class ContributorActivity extends AppCompatActivity {
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | ActivityHelper.applyTheme(this);
19 | try {
20 | setContentView(R.layout.activity_contributors);
21 | } catch (Exception e) {
22 | MarkdownView.closeOnMissingWebView(this, e);
23 | }
24 | Toolbar toolbar = findViewById(R.id.toolbar);
25 | setSupportActionBar(toolbar);
26 | ActionBar actionBar = getSupportActionBar();
27 | if (actionBar != null) {
28 | actionBar.setDisplayHomeAsUpEnabled(true);
29 | actionBar.setDisplayShowHomeEnabled(true);
30 | }
31 |
32 | MarkdownView markdownView = findViewById(R.id.markdownView);
33 | markdownView.loadAsset("contributors.md");
34 | }
35 |
36 | @Override
37 | public boolean onSupportNavigateUp() {
38 | onBackPressed();
39 | return true;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Activities/ShortcutServiceActivity.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Activities
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import android.widget.Toast
6 | import androidx.appcompat.app.AppCompatActivity
7 | import ca.pkay.rcloneexplorer.R
8 | import ca.pkay.rcloneexplorer.workmanager.SyncManager
9 | import ca.pkay.rcloneexplorer.workmanager.SyncWorker.Companion.EXTRA_TASK_ID
10 | import ca.pkay.rcloneexplorer.workmanager.SyncWorker.Companion.TASK_SYNC_ACTION
11 |
12 | class ShortcutServiceActivity : AppCompatActivity() {
13 |
14 | private val TAG = "ShortcutServiceActivity"
15 |
16 | override fun onCreate(savedInstanceState: Bundle?) {
17 | super.onCreate(savedInstanceState)
18 | moveTaskToBack(true)
19 |
20 | Log.e(TAG, "Recieved start signal!")
21 |
22 | if(intent.action == TASK_SYNC_ACTION) {
23 | Log.e(TAG, "Recieved valid intent.")
24 | val id = intent.extras?.getLong(EXTRA_TASK_ID)
25 | if(id != null) {
26 | SyncManager(this.baseContext).queue(id)
27 | Toast.makeText(this, getString(R.string.shortcut_start_service), Toast.LENGTH_SHORT).show()
28 | } else {
29 | Toast.makeText(this, getString(R.string.shortcut_missing_id), Toast.LENGTH_SHORT).show()
30 | }
31 | }
32 |
33 | Log.e(TAG, "Finish up.")
34 | finish()
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/BroadcastReceivers/BootReciever.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.BroadcastReceivers;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import ca.pkay.rcloneexplorer.Services.TriggerService;
8 |
9 | public class BootReciever extends BroadcastReceiver {
10 |
11 | @Override
12 | public void onReceive(Context context, Intent intent) {
13 | if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
14 | new TriggerService(context).queueTrigger();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/BroadcastReceivers/ClearReportBroadcastReciever.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.BroadcastReceivers
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import androidx.datastore.preferences.core.edit
7 | import ca.pkay.rcloneexplorer.notifications.ReportNotifications
8 | import ca.pkay.rcloneexplorer.notifications.dataStore
9 | import kotlinx.coroutines.runBlocking
10 |
11 |
12 | class ClearReportBroadcastReciever: BroadcastReceiver() {
13 |
14 | override fun onReceive(context: Context?, intent: Intent) {
15 | val action = intent.action
16 | if (action == ReportNotifications.REPORT_SUCCESS_DELETE_INTENT) {
17 | if(context != null){
18 | runBlocking {
19 | context.dataStore.edit { settings ->
20 | settings[ReportNotifications.NOTIFICATION_CACHE_SUCCESS_PREFERENCE] = ""
21 | }
22 | }
23 | }
24 | }
25 | if (action == ReportNotifications.REPORT_FAIL_DELETE_INTENT) {
26 | if(context != null){
27 | runBlocking {
28 | context.dataStore.edit { settings ->
29 | settings[ReportNotifications.NOTIFICATION_CACHE_FAIL_PREFERENCE] = ""
30 | }
31 | }
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/BroadcastReceivers/ServeCancelAction.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.BroadcastReceivers;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import ca.pkay.rcloneexplorer.Services.StreamingService;
8 |
9 | public class ServeCancelAction extends BroadcastReceiver {
10 |
11 | @Override
12 | public void onReceive(Context context, Intent intent) {
13 | Intent serveIntent = new Intent(context, StreamingService.class);
14 | context.stopService(serveIntent);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/BroadcastReceivers/SyncRestartAction.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.BroadcastReceivers;
2 |
3 | import static ca.pkay.rcloneexplorer.workmanager.SyncWorker.EXTRA_TASK_ID;
4 |
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 |
9 | import ca.pkay.rcloneexplorer.workmanager.SyncManager;
10 |
11 | /**
12 | * This class requires a receiver declaration in the manifest
13 | */
14 | public class SyncRestartAction extends BroadcastReceiver {
15 |
16 | @Override
17 | public void onReceive(Context context, Intent intent) {
18 | SyncManager sm = new SyncManager(context);
19 | sm.queue(intent.getLongExtra(EXTRA_TASK_ID, -1));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/BroadcastReceivers/TriggerReciever.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.BroadcastReceivers;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 |
8 | import ca.pkay.rcloneexplorer.Services.TriggerService;
9 | import ca.pkay.rcloneexplorer.util.FLog;
10 |
11 | public class TriggerReciever extends BroadcastReceiver {
12 |
13 | private static final String TAG = "TriggerReciever";
14 |
15 | @Override
16 | public void onReceive(Context context, Intent intent) {
17 | FLog.e(TAG, "Recieved Intent");
18 |
19 | assert intent != null;
20 | if(intent.getAction().equals(TriggerService.TRIGGER_RECIEVE)){
21 | long i = intent.getLongExtra(TriggerService.TRIGGER_ID, -1);
22 | FLog.e(TAG, "Start Trigger: "+i);
23 | if(i==-1)
24 | return;
25 |
26 | Intent service = new Intent(context, TriggerService.class);
27 | service.setAction(TriggerService.TRIGGER_RECIEVE);
28 | service.putExtra(TriggerService.TRIGGER_ID, i);
29 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
30 | context.startForegroundService(service);
31 | }else{
32 | context.startService(service);
33 | }
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Database/json/Exporter.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Database.json;
2 |
3 | import android.content.Context;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 | import org.json.JSONObject;
8 |
9 | import ca.pkay.rcloneexplorer.Database.DatabaseHandler;
10 | import ca.pkay.rcloneexplorer.Items.Filter;
11 | import ca.pkay.rcloneexplorer.Items.Task;
12 | import ca.pkay.rcloneexplorer.Items.Trigger;
13 |
14 | public class Exporter {
15 |
16 | public static String create(Context context) throws JSONException {
17 |
18 | DatabaseHandler dbHandler = new DatabaseHandler(context);
19 | JSONObject main = new JSONObject();
20 |
21 | JSONArray tasks = new JSONArray();
22 | for(Task task : dbHandler.getAllTasks()){
23 | tasks.put(task.asJSON());
24 | }
25 | main.put("tasks", tasks);
26 |
27 | JSONArray triggers = new JSONArray();
28 | for(Trigger trigger : dbHandler.getAllTrigger()){
29 | triggers.put(trigger.asJSON());
30 | }
31 | main.put("trigger", triggers);
32 |
33 | JSONArray filters = new JSONArray();
34 | for(Filter filter : dbHandler.getAllFilters()){
35 | filters.put(filter.asJSON());
36 | }
37 | main.put("filters", filters);
38 |
39 |
40 | return main.toString();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/Dialogs.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Dialogs;
2 |
3 | import androidx.annotation.Nullable;
4 | import androidx.fragment.app.DialogFragment;
5 |
6 | public class Dialogs {
7 |
8 | /**
9 | * Dismiss a dialog, but only if it is still attached to a host activity.
10 | *
11 | * This should be used especially in callbacks, since they have a higher
12 | * chance of being executed in a different lifecycle phase and thus an
13 | * elevated propability of calling DialogFrament.dismiss() on an invalid
14 | * fragment.
15 | * @param dialog the dialog to dismiss
16 | */
17 | public static void dismissSilently(@Nullable DialogFragment dialog) {
18 | if(dialog != null) {
19 | if(dialog.isStateSaved()){
20 | dialog.dismissAllowingStateLoss();
21 | } else if(dialog.isAdded()) {
22 | dialog.dismiss();
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FolderSelectorCallback.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Fragments;
2 |
3 | public interface FolderSelectorCallback {
4 | public void selectFolder(String path);
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Items/FilterEntry.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Items;
2 |
3 | import android.content.Context;
4 |
5 | import ca.pkay.rcloneexplorer.R;
6 |
7 | public class FilterEntry {
8 |
9 | public static final int FILTER_INCLUDE = 0;
10 | public static final int FILTER_EXCLUDE = 1;
11 |
12 | public int filterType = FILTER_EXCLUDE;
13 |
14 | public String filter;
15 |
16 |
17 | public FilterEntry(int filterType, String filter) {
18 | this.filterType = filterType;
19 | this.filter = filter;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Services/SyncService.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Services
2 |
3 | import android.app.IntentService
4 | import android.content.Intent
5 | import android.util.Log
6 | import ca.pkay.rcloneexplorer.Database.DatabaseHandler
7 | import ca.pkay.rcloneexplorer.workmanager.SyncManager
8 | import de.felixnuesse.extract.extensions.tag
9 |
10 |
11 | /**
12 | * This service is only meant to provide other apps
13 | * the ability to start a task.
14 | * Do not actually implement any sync changes, they only belong in the SyncManager/Worker!
15 | */
16 | class SyncService: IntentService("ca.pkay.rcexplorer.SYNC_SERCVICE"){
17 | override fun onHandleIntent(intent: Intent?) {
18 | if(intent == null){
19 | return
20 | }
21 |
22 | val action = intent.action
23 | val taskId = intent.getIntExtra("task", -1)
24 | // Todo: Allow SyncWorker to run in silent mode, or remove this!
25 | val silentRun = intent.getBooleanExtra("notification", true)
26 |
27 |
28 | if (action.equals("START_TASK")) {
29 | val db = DatabaseHandler(this)
30 | for (task in db.allTasks) {
31 | if (task.id == taskId.toLong()) {
32 | SyncManager(this).queue(task)
33 | }
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Settings/FileAccessPreferencesFragment.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Settings
2 |
3 | import android.content.SharedPreferences
4 | import android.os.Bundle
5 | import androidx.preference.PreferenceFragmentCompat
6 | import androidx.preference.PreferenceManager
7 | import ca.pkay.rcloneexplorer.R
8 |
9 | class FileAccessPreferencesFragment : PreferenceFragmentCompat() {
10 |
11 |
12 | private lateinit var sharedPreferences: SharedPreferences
13 |
14 |
15 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
16 | setPreferencesFromResource(R.xml.settings_fileaccess_preferences, rootKey)
17 | sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
18 | requireActivity().title = getString(R.string.pref_header_file_access)
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/Settings/ThemingPreferencesFragment.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.Settings
2 |
3 | import android.app.Activity
4 | import android.content.SharedPreferences
5 | import android.os.Bundle
6 | import androidx.preference.PreferenceFragmentCompat
7 | import androidx.preference.PreferenceManager
8 | import ca.pkay.rcloneexplorer.R
9 |
10 | class ThemingPreferencesFragment : PreferenceFragmentCompat(),
11 | SharedPreferences.OnSharedPreferenceChangeListener {
12 |
13 | private lateinit var sharedPreferences: SharedPreferences
14 |
15 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
16 | setPreferencesFromResource(R.xml.settings_theming_preferences, rootKey)
17 | sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
18 | requireActivity().title = getString(R.string.look_and_feel)
19 |
20 | val new = getString(R.string.pref_key_theme)
21 | val old = getString(R.string.pref_key_theme_old)
22 |
23 | if(sharedPreferences.contains(old)) {
24 | sharedPreferences.edit()
25 | .putString(new, sharedPreferences.getString(new, "0"))
26 | .remove(old)
27 | .apply()
28 | }
29 |
30 | sharedPreferences.registerOnSharedPreferenceChangeListener(this)
31 | }
32 |
33 | override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
34 | if(key == activity?.getString(R.string.pref_key_theme)) {
35 | requireActivity().recreate()
36 | }
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/SpinnerAdapters/FilterSpinnerAdapter.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.SpinnerAdapters
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.ArrayAdapter
9 | import android.widget.TextView
10 | import androidx.core.content.ContextCompat
11 | import ca.pkay.rcloneexplorer.R
12 |
13 | class FilterSpinnerAdapter(context: Context, resource: Int, objects: List) :
14 | ArrayAdapter(context, resource, objects) {
15 |
16 | override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
17 | val view = convertView ?: LayoutInflater.from(context).inflate(android.R.layout.simple_spinner_dropdown_item, parent, false)
18 | val textView = view.findViewById(android.R.id.text1)
19 |
20 | // Set special styling for "No Filter" option
21 | if (getItem(position) == context.getString(R.string.task_edit_filter_nofilter)) {
22 | textView.setTextColor(ContextCompat.getColor(context, R.color.textColorTertiary))
23 | textView.setTypeface(null, Typeface.BOLD_ITALIC)
24 | } else {
25 | textView.setTextColor(ContextCompat.getColor(context, R.color.textColorPrimary))
26 | textView.setTypeface(null, Typeface.NORMAL)
27 | }
28 |
29 | textView.text = getItem(position)
30 | return view
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/notifications/support/ErrorObject.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.notifications.support
2 |
3 | class ErrorObject(var mErrorObject: String, var mErrorMessage: String) {}
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/rclone/OptionExampleItem.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.rclone
2 |
3 | class OptionExampleItem(var Value: String, var Help: String, var Provider: String){}
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/util/FlagsUtil.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.util
2 |
3 | import android.app.PendingIntent
4 | import android.os.Build
5 |
6 | class FlagsUtil {
7 |
8 | companion object {
9 |
10 | fun getFlagImmutable() : Int {
11 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
12 | PendingIntent.FLAG_IMMUTABLE
13 | } else {
14 | 0
15 | }
16 | }
17 |
18 | fun getFlagImmutable(flag: Int) : Int {
19 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
20 | PendingIntent.FLAG_IMMUTABLE and flag
21 | } else {
22 | flag
23 | }
24 | }
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/util/LargeParcel.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.util;
2 |
3 | import android.os.Bundle;
4 | import android.os.Parcel;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | public class LargeParcel {
9 |
10 | public static int calculateBundleSize(@NonNull Bundle bundle) {
11 | Parcel parcel = Parcel.obtain();
12 | parcel.writeBundle(bundle);
13 | int size = parcel.dataSize();
14 | parcel.recycle();
15 | return size;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/util/Rfc3339Deserializer.java:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.util;
2 |
3 | import com.fasterxml.jackson.core.JsonParser;
4 | import com.fasterxml.jackson.core.JsonProcessingException;
5 | import com.fasterxml.jackson.databind.DeserializationContext;
6 | import com.fasterxml.jackson.databind.JsonNode;
7 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
8 |
9 | import java.io.IOException;
10 | import java.text.ParseException;
11 |
12 | import ca.pkay.rcloneexplorer.RcloneRcd;
13 | import io.github.x0b.rfc3339parser.Rfc3339Parser;
14 | import io.github.x0b.rfc3339parser.Rfc3339Strict;
15 |
16 | public class Rfc3339Deserializer extends StdDeserializer {
17 |
18 | private Rfc3339Parser rfc3339Parser;
19 |
20 | protected Rfc3339Deserializer() {
21 | super(Rfc3339Deserializer.class);
22 | rfc3339Parser = new Rfc3339Strict();
23 | }
24 |
25 | @Override
26 | public Long deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
27 | JsonNode timeNode = parser.getCodec().readTree(parser);
28 | try {
29 | return rfc3339Parser.parseCalendar(timeNode.asText()).getTimeInMillis();
30 | } catch (ParseException e) {
31 | return 0L;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/util/SharedPreferencesUtil.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.util
2 |
3 | import android.content.Context
4 | import androidx.preference.PreferenceManager
5 |
6 | class SharedPreferencesUtil {
7 |
8 |
9 | companion object {
10 | public fun setLastOpenFragment(context: Context, lastFragmentId: Int) {
11 | val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context).edit()
12 | sharedPreferences.putInt("last_open_fragment", lastFragmentId)
13 | sharedPreferences.apply()
14 | }
15 |
16 | public fun getLastOpenFragment(context: Context, defaultSelection: Int): Int {
17 | val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
18 | return sharedPreferences.getInt("last_open_fragment", defaultSelection)
19 | }
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/pkay/rcloneexplorer/workmanager/Type.kt:
--------------------------------------------------------------------------------
1 | package ca.pkay.rcloneexplorer.workmanager
2 |
3 | enum class Type {
4 | DOWNLOAD,
5 | UPLOAD,
6 | MOVE,
7 | DELETE
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/extensions/TAG.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.extensions
2 |
3 | fun Any.tag(): String { return this::class.java.simpleName }
4 |
5 | // fragments do have a tag() function. Use TAG() instead.
6 | fun Any.TAG(): String { return this::class.java.simpleName }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/notifications/DiscardChannels.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.notifications
2 |
3 | import android.app.NotificationManager
4 | import android.content.Context
5 | import android.os.Build
6 |
7 | class DiscardChannels {
8 | companion object {
9 | fun discard(context: Context) {
10 | val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
11 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
12 | notificationManager.deleteNotificationChannel("ca.pkay.rcexplorer.UPLOAD_CHANNEL")
13 | notificationManager.deleteNotificationChannel("ca.pkay.rcexplorer.DOWNLOAD_CHANNEL")
14 | }
15 |
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/onboarding/SlideLeaveInterface.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.onboarding
2 |
3 | interface SlideLeaveInterface {
4 |
5 | fun allowSlideLeave(id: String): Boolean
6 |
7 | fun onSlideLeavePrevented(id: String)
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/onboarding/SlideSwitchCallback.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.onboarding
2 |
3 | interface SlideSwitchCallback {
4 |
5 | fun switchChanged(id: String, isChecked: Boolean)
6 |
7 | }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/settings/language/LocaleAdapter.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.settings.language
2 |
3 | import java.util.Locale
4 |
5 |
6 | class LocaleAdapter(private var mLocale: Locale) {
7 |
8 | override fun toString(): String {
9 | return mLocale.displayLanguage
10 | }
11 |
12 | fun getLocale(): Locale {
13 | return mLocale
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/de/felixnuesse/extract/settings/preferences/ButtonPreference.kt:
--------------------------------------------------------------------------------
1 | package de.felixnuesse.extract.settings.preferences
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.View
6 | import android.widget.Button
7 | import androidx.preference.Preference
8 | import androidx.preference.PreferenceViewHolder
9 | import ca.pkay.rcloneexplorer.R
10 |
11 |
12 | /**
13 | * https://stackoverflow.com/a/70795847
14 | */
15 |
16 |
17 | class ButtonPreference(context: Context, attrs: AttributeSet): Preference(context, attrs) {
18 |
19 | private lateinit var holder: PreferenceViewHolder
20 | private var clickListener: View.OnClickListener? = null
21 | private var text: String? = null
22 |
23 | init {
24 | widgetLayoutResource = R.layout.preference_button;
25 | }
26 |
27 | override fun onBindViewHolder(holder: PreferenceViewHolder) {
28 | super.onBindViewHolder(holder)
29 | this.holder = holder
30 | updateViews()
31 | }
32 |
33 | fun setButtonOnClick(listener: View.OnClickListener) {
34 | clickListener = listener
35 | updateViews()
36 | }
37 |
38 | fun setButtonText(text: String) {
39 | this.text = text
40 | updateViews()
41 | }
42 |
43 | private fun updateViews() {
44 | if(this::holder.isInitialized) {
45 | val button = holder.itemView.findViewById