├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── android-build-master.yml ├── .gitignore ├── LICENSE ├── README.org ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── schemas │ └── com.orgzly.android.db.OrgzlyDatabase │ │ ├── 150.json │ │ ├── 151.json │ │ ├── 152.json │ │ ├── 153.json │ │ ├── 154.json │ │ ├── 155.json │ │ └── 156.json └── src │ ├── androidTest │ ├── AndroidManifest.xml │ ├── assets │ │ ├── encoding │ │ │ ├── Chinese-Lipsum.org │ │ │ ├── ascii.org │ │ │ ├── few_chinese_characters.org │ │ │ ├── iso-8859-15-dos.org │ │ │ ├── org-blog-articles.org │ │ │ └── org-people.org │ │ ├── html │ │ │ ├── dv.org │ │ │ └── zh.org │ │ ├── images │ │ │ ├── logo.png │ │ │ └── logo11w.org │ │ ├── lipsum │ │ │ ├── Arabic-Lipsum.org │ │ │ ├── Chinese-Lipsum.org │ │ │ ├── Greek-Lipsum.org │ │ │ ├── Hebrew-Lipsum.org │ │ │ ├── Hindi-Lipsum.org │ │ │ ├── Japanese-Lipsum.org │ │ │ ├── L33tspeak-Lipsum.org │ │ │ └── Russian-Lipsum.org │ │ └── org │ │ │ ├── large.org │ │ │ ├── links-heavy-content.org │ │ │ └── markup-heavy-content.org │ └── java │ │ └── com │ │ └── orgzly │ │ └── android │ │ ├── AllTestSuite.kt │ │ ├── LipsumBookGenerator.java │ │ ├── OrgzlyTest.java │ │ ├── OrgzlyTestRunner.kt │ │ ├── TestUtils.java │ │ ├── espresso │ │ ├── ActionModeTest.java │ │ ├── AgendaFragmentTest.java │ │ ├── BookChooserActivityTest.java │ │ ├── BookPrefaceTest.kt │ │ ├── BookTest.java │ │ ├── BooksSortOrderTest.kt │ │ ├── BooksTest.java │ │ ├── CreatedAtPropertyTest.java │ │ ├── ExternalLinksTest.kt │ │ ├── InternalLinksTest.kt │ │ ├── MiscTest.java │ │ ├── NewNoteTest.java │ │ ├── NoteEventsTest.kt │ │ ├── NoteFragmentTest.kt │ │ ├── OrgProtocolTest.kt │ │ ├── QueryFragmentTest.java │ │ ├── ReposActivityTest.java │ │ ├── SavedSearchesFragmentTest.java │ │ ├── SettingsChangeTest.java │ │ ├── SettingsFragmentTest.java │ │ ├── ShareActivityTest.kt │ │ ├── SyncingTest.java │ │ └── util │ │ │ ├── EspressoUtils.java │ │ │ ├── NestedScrollViewExtension.kt │ │ │ └── ScreenshotsTakingNotATest.kt │ │ ├── misc │ │ ├── BookNameTest.java │ │ ├── BookParsingTest.java │ │ ├── CreatedAtTest.kt │ │ ├── DataTest.kt │ │ ├── LogSomethingNotTest.kt │ │ ├── SettingsTest.kt │ │ ├── StateChangeTest.kt │ │ ├── StructureTest.kt │ │ └── UriTest.java │ │ ├── query │ │ ├── QueryTest.kt │ │ ├── QueryTokenizerTest.kt │ │ └── QueryUtilsTest.kt │ │ ├── reminders │ │ └── NoteRemindersTest.kt │ │ ├── repos │ │ ├── DataRepositoryTest.java │ │ ├── DirectoryRepoTest.java │ │ ├── DropboxRepoTest.java │ │ ├── LocalDbRepoTest.java │ │ ├── RepoFactoryTest.java │ │ └── SyncTest.java │ │ ├── ui │ │ └── ImageLoaderTest.kt │ │ ├── uiautomator │ │ └── ListWidgetTest.java │ │ ├── usecase │ │ ├── NoteUpdateDeadlineTimeTest.kt │ │ └── NoteUpdateScheduledTimeTest.kt │ │ └── util │ │ ├── AgendaUtilsTest.kt │ │ ├── EncodingDetectTest.java │ │ ├── MiscUtilsTest.java │ │ ├── OrgFormatterLinkTest.kt │ │ ├── OrgFormatterMiscTest.java │ │ ├── OrgFormatterSpeedTest.java │ │ ├── OrgFormatterStyleTextTest.java │ │ ├── OrgFormatterTest.java │ │ └── UriUtilsTest.java │ └── main │ ├── AndroidManifest.xml │ ├── cic_launcher-playstore.png │ ├── java │ └── com │ │ └── orgzly │ │ └── android │ │ ├── ActionReceiver.kt │ │ ├── App.java │ │ ├── AppExecutors.kt │ │ ├── AppIntent.java │ │ ├── AppUnderTest.kt │ │ ├── BookFormat.java │ │ ├── BookName.java │ │ ├── BookUtils.java │ │ ├── BootCompletedReceiver.java │ │ ├── LocalStorage.java │ │ ├── NewNoteBroadcastReceiver.java │ │ ├── NotesOrgExporter.kt │ │ ├── NotificationBroadcastReceiver.kt │ │ ├── NotificationChannels.kt │ │ ├── SharingShortcutsManager.kt │ │ ├── TimeChangeBroadcastReceiver.kt │ │ ├── data │ │ ├── DataRepository.kt │ │ ├── DbRepoBookRepository.kt │ │ ├── logs │ │ │ ├── AppLogsRepository.kt │ │ │ ├── DatabaseAppLogsRepository.kt │ │ │ └── LogEntry.kt │ │ └── mappers │ │ │ └── OrgMapper.kt │ │ ├── db │ │ ├── NotesClipboard.kt │ │ ├── OrgzlyDatabase.kt │ │ ├── PreRoomMigration.kt │ │ ├── TypeConverters.kt │ │ ├── dao │ │ │ ├── AppLogDao.kt │ │ │ ├── BaseDao.kt │ │ │ ├── BookDao.kt │ │ │ ├── BookLinkDao.kt │ │ │ ├── BookSyncDao.kt │ │ │ ├── BookViewDao.kt │ │ │ ├── DbRepoBookDao.kt │ │ │ ├── NoteAncestorDao.kt │ │ │ ├── NoteDao.kt │ │ │ ├── NoteEventDao.kt │ │ │ ├── NotePropertyDao.kt │ │ │ ├── NoteViewDao.kt │ │ │ ├── OrgRangeDao.kt │ │ │ ├── OrgTimestampDao.kt │ │ │ ├── ReminderTimeDao.kt │ │ │ ├── RepoDao.kt │ │ │ ├── RookDao.kt │ │ │ ├── RookUrlDao.kt │ │ │ ├── SavedSearchDao.kt │ │ │ └── VersionedRookDao.kt │ │ ├── entity │ │ │ ├── AppLog.kt │ │ │ ├── Book.kt │ │ │ ├── BookAction.kt │ │ │ ├── BookLink.kt │ │ │ ├── BookSync.kt │ │ │ ├── BookView.kt │ │ │ ├── DbRepoBook.kt │ │ │ ├── Note.kt │ │ │ ├── NoteAncestor.kt │ │ │ ├── NoteEvent.kt │ │ │ ├── NotePosition.kt │ │ │ ├── NoteProperty.kt │ │ │ ├── NoteView.kt │ │ │ ├── OrgRange.kt │ │ │ ├── OrgTimestamp.kt │ │ │ ├── Repo.kt │ │ │ ├── Rook.kt │ │ │ ├── RookUrl.kt │ │ │ ├── SavedSearch.kt │ │ │ └── VersionedRook.kt │ │ └── mappers │ │ │ └── OrgTimestampMapper.kt │ │ ├── di │ │ ├── AppComponent.kt │ │ └── module │ │ │ ├── ApplicationModule.kt │ │ │ ├── DataModule.kt │ │ │ └── DatabaseModule.kt │ │ ├── git │ │ ├── GitFileSynchronizer.java │ │ ├── GitPreferences.java │ │ ├── GitPreferencesFromRepoPrefs.java │ │ ├── GitSSHKeyTransportSetter.java │ │ ├── GitTransportSetter.java │ │ └── HTTPSTransportSetter.java │ │ ├── prefs │ │ ├── AppPreferences.java │ │ ├── AppPreferencesValues.java │ │ ├── IntegerPreference.kt │ │ ├── IntegerPreferenceFragment.kt │ │ ├── NotePopupPreference.kt │ │ ├── NotePopupPreferenceFragment.kt │ │ ├── RepoPreferences.java │ │ ├── StateWorkflows.java │ │ ├── StatesPreference.java │ │ ├── StatesPreferenceFragment.kt │ │ ├── TimePreference.kt │ │ └── TimePreferenceFragment.kt │ │ ├── query │ │ ├── Condition.kt │ │ ├── Options.kt │ │ ├── Query.kt │ │ ├── QueryInterval.kt │ │ ├── QueryParser.kt │ │ ├── QueryTokenizer.kt │ │ ├── QueryUtils.kt │ │ ├── Relation.kt │ │ ├── SortOrder.kt │ │ ├── StateType.kt │ │ ├── TimeUtils.kt │ │ ├── sql │ │ │ ├── SqlQuery.kt │ │ │ └── SqliteQueryBuilder.kt │ │ └── user │ │ │ ├── BasicQueryParser.kt │ │ │ ├── DottedQueryBuilder.kt │ │ │ ├── DottedQueryParser.kt │ │ │ ├── InternalQueryBuilder.kt │ │ │ └── InternalQueryParser.kt │ │ ├── reminders │ │ ├── LastRun.kt │ │ ├── NoteReminder.kt │ │ ├── NoteReminderPayload.kt │ │ ├── NoteReminders.kt │ │ ├── RemindersBroadcastReceiver.kt │ │ ├── RemindersNotifications.kt │ │ └── RemindersScheduler.kt │ │ ├── repos │ │ ├── ContentRepo.java │ │ ├── DatabaseRepo.java │ │ ├── DirectoryRepo.java │ │ ├── DropboxClient.java │ │ ├── DropboxRepo.java │ │ ├── GitRepo.java │ │ ├── MockRepo.java │ │ ├── RepoFactory.kt │ │ ├── RepoType.kt │ │ ├── RepoUtils.java │ │ ├── RepoWithProps.kt │ │ ├── Rook.java │ │ ├── SyncRepo.java │ │ ├── TwoWaySyncRepo.kt │ │ ├── TwoWaySyncResult.kt │ │ ├── VersionedRook.kt │ │ └── WebdavRepo.kt │ │ ├── savedsearch │ │ ├── FileSavedSearchStore.kt │ │ └── SavedSearchStore.kt │ │ ├── sync │ │ ├── AutoSync.kt │ │ ├── BookNamesake.java │ │ ├── BookSyncStatus.kt │ │ ├── SyncRunner.kt │ │ ├── SyncState.kt │ │ ├── SyncUtils.kt │ │ └── SyncWorker.kt │ │ ├── ui │ │ ├── AgendaTimeType.kt │ │ ├── AppBar.kt │ │ ├── AppSnackbar.kt │ │ ├── BookChooserActivity.java │ │ ├── BottomActionBar.kt │ │ ├── Breadcrumbs.kt │ │ ├── CommonActivity.kt │ │ ├── CommonActivityLifecycleCallbacks.java │ │ ├── CommonFragment.kt │ │ ├── CommonViewModel.kt │ │ ├── DisplayManager.java │ │ ├── ImageLoader.kt │ │ ├── LauncherActivity.kt │ │ ├── NotePlace.java │ │ ├── NotePriorities.kt │ │ ├── NoteStates.kt │ │ ├── OnViewHolderClickListener.kt │ │ ├── Place.java │ │ ├── SelectableItemAdapter.kt │ │ ├── Selection.kt │ │ ├── SingleLiveEvent.java │ │ ├── SpanUtils.kt │ │ ├── SpinnerValues.java │ │ ├── SyncProgressViewModel.kt │ │ ├── SyncShortcutActivity.java │ │ ├── TemplateChooserActivity.java │ │ ├── TimeType.kt │ │ ├── books │ │ │ ├── BooksAdapter.kt │ │ │ ├── BooksFragment.kt │ │ │ ├── BooksViewModel.kt │ │ │ └── BooksViewModelFactory.kt │ │ ├── dialogs │ │ │ ├── DelayPickerDialog.kt │ │ │ ├── NoteStateDialog.kt │ │ │ ├── PeriodWithTypePickerDialog.kt │ │ │ ├── RepeaterPickerDialog.kt │ │ │ ├── SimpleOneLinerDialog.kt │ │ │ ├── TimestampDialogFragment.kt │ │ │ ├── TimestampDialogViewModel.kt │ │ │ ├── TimestampDialogViewModelFactory.kt │ │ │ ├── WarningPeriodPickerDialog.kt │ │ │ └── WhatsNewDialog.kt │ │ ├── dndrv │ │ │ ├── ItemTouchHelperAdapter.kt │ │ │ ├── ItemTouchHelperViewHolder.kt │ │ │ ├── NotePopupPreferenceRecyclerListAdapter.kt │ │ │ ├── OnStartDragListener.kt │ │ │ └── SimpleItemTouchHelperCallback.kt │ │ ├── drawer │ │ │ ├── DrawerItem.kt │ │ │ └── DrawerNavigationView.kt │ │ ├── logs │ │ │ ├── AppLogsActivity.kt │ │ │ ├── AppLogsViewModel.kt │ │ │ └── AppLogsViewModelFactory.kt │ │ ├── main │ │ │ ├── ActivityForResult.kt │ │ │ ├── Fab.kt │ │ │ ├── MainActivity.java │ │ │ ├── MainActivityViewModel.kt │ │ │ ├── MainActivityViewModelFactory.kt │ │ │ ├── OrgProtocol.kt │ │ │ ├── SearchViewSetup.kt │ │ │ └── SharedMainActivityViewModel.kt │ │ ├── note │ │ │ ├── NoteBuilder.kt │ │ │ ├── NoteFragment.kt │ │ │ ├── NotePayload.kt │ │ │ ├── NoteViewModel.kt │ │ │ └── NoteViewModelFactory.kt │ │ ├── notes │ │ │ ├── ItemGestureDetector.kt │ │ │ ├── NoteItemViewBinder.kt │ │ │ ├── NoteItemViewHolder.kt │ │ │ ├── NotePopup.kt │ │ │ ├── NotesFragment.kt │ │ │ ├── OnSwipeListener.kt │ │ │ ├── book │ │ │ │ ├── BookAdapter.kt │ │ │ │ ├── BookFragment.kt │ │ │ │ ├── BookPrefaceFragment.kt │ │ │ │ ├── BookViewModel.kt │ │ │ │ ├── BookViewModelFactory.kt │ │ │ │ ├── ListAdapterWithHeaders.kt │ │ │ │ └── PrefaceItemViewBinder.kt │ │ │ └── query │ │ │ │ ├── QueryFragment.kt │ │ │ │ ├── QueryViewModel.kt │ │ │ │ ├── QueryViewModelFactory.kt │ │ │ │ ├── agenda │ │ │ │ ├── AgendaAdapter.kt │ │ │ │ ├── AgendaFragment.kt │ │ │ │ ├── AgendaItem.kt │ │ │ │ └── AgendaItems.kt │ │ │ │ └── search │ │ │ │ ├── SearchAdapter.kt │ │ │ │ └── SearchFragment.kt │ │ ├── notifications │ │ │ ├── Notifications.java │ │ │ └── SyncNotifications.kt │ │ ├── refile │ │ │ ├── RefileAdapter.kt │ │ │ ├── RefileFragment.kt │ │ │ ├── RefileLocation.kt │ │ │ ├── RefileViewModel.kt │ │ │ └── RefileViewModelFactory.kt │ │ ├── repo │ │ │ ├── BrowserActivity.kt │ │ │ ├── RepoViewModel.kt │ │ │ ├── RepoViewModelFactory.kt │ │ │ ├── directory │ │ │ │ └── DirectoryRepoActivity.kt │ │ │ ├── dropbox │ │ │ │ └── DropboxRepoActivity.kt │ │ │ ├── git │ │ │ │ └── GitRepoActivity.kt │ │ │ └── webdav │ │ │ │ ├── WebdavRepoActivity.kt │ │ │ │ ├── WebdavRepoViewModel.kt │ │ │ │ └── WebdavRepoViewModelFactory.kt │ │ ├── repos │ │ │ ├── ReposActivity.kt │ │ │ ├── ReposViewModel.kt │ │ │ └── ReposViewModelFactory.kt │ │ ├── savedsearch │ │ │ └── SavedSearchFragment.java │ │ ├── savedsearches │ │ │ ├── SavedSearchesAdapter.kt │ │ │ ├── SavedSearchesFragment.kt │ │ │ ├── SavedSearchesViewModel.kt │ │ │ └── SavedSearchesViewModelFactory.kt │ │ ├── settings │ │ │ ├── SettingsActivity.kt │ │ │ └── SettingsFragment.kt │ │ ├── share │ │ │ └── ShareActivity.java │ │ ├── stickyheaders │ │ │ ├── StickyHeaders.java │ │ │ └── StickyHeadersLinearLayoutManager.java │ │ ├── sync │ │ │ ├── SyncFragment.kt │ │ │ └── SyncViewModel.kt │ │ ├── util │ │ │ ├── ActivityUtils.kt │ │ │ ├── Extensions.kt │ │ │ ├── KeyboardUtils.kt │ │ │ ├── ListViewUtils.java │ │ │ ├── SystemActions.kt │ │ │ ├── SystemServices.kt │ │ │ ├── TitleGenerator.java │ │ │ └── ViewUtils.java │ │ └── views │ │ │ ├── GesturedListView.java │ │ │ ├── GesturedListViewItemMenu.java │ │ │ ├── GesturedListViewItemMenus.java │ │ │ ├── WhatsNewChange.kt │ │ │ ├── richtext │ │ │ ├── ActionableRichTextView.kt │ │ │ ├── RichText.kt │ │ │ ├── RichTextEdit.kt │ │ │ ├── RichTextEditWatcher.kt │ │ │ └── RichTextView.kt │ │ │ └── style │ │ │ ├── BoldSpan.kt │ │ │ ├── CheckboxSpan.kt │ │ │ ├── CodeSpan.kt │ │ │ ├── CustomIdLinkSpan.kt │ │ │ ├── DrawerMarkerSpan.kt │ │ │ ├── DrawerSpan.kt │ │ │ ├── FileLinkSpan.kt │ │ │ ├── FileOrNotLinkSpan.kt │ │ │ ├── IdLinkSpan.kt │ │ │ ├── ItalicSpan.kt │ │ │ ├── LinkSpan.kt │ │ │ ├── Offsetting.kt │ │ │ ├── SearchLinkSpan.kt │ │ │ ├── StrikeSpan.kt │ │ │ ├── UnderlinedSpan.kt │ │ │ ├── UrlLinkSpan.kt │ │ │ └── VerbatimSpan.kt │ │ ├── usecase │ │ ├── BookCreate.kt │ │ ├── BookCycleVisibility.kt │ │ ├── BookDelete.kt │ │ ├── BookExport.kt │ │ ├── BookExportToUri.kt │ │ ├── BookForceLoad.kt │ │ ├── BookForceSave.kt │ │ ├── BookImportFromUri.kt │ │ ├── BookImportGettingStarted.kt │ │ ├── BookLinkUpdate.kt │ │ ├── BookRename.kt │ │ ├── BookScrollToNote.kt │ │ ├── BookSparseTreeForNote.kt │ │ ├── BookUpdatePreface.kt │ │ ├── DatabaseClear.kt │ │ ├── LinkFindTarget.kt │ │ ├── NoteCopy.kt │ │ ├── NoteCreate.kt │ │ ├── NoteCreateFromNotification.kt │ │ ├── NoteCut.kt │ │ ├── NoteDelete.kt │ │ ├── NoteDemote.kt │ │ ├── NoteFindWithProperty.kt │ │ ├── NoteMove.kt │ │ ├── NotePaste.kt │ │ ├── NotePromote.kt │ │ ├── NoteRefile.kt │ │ ├── NoteReparseStateAndTitles.kt │ │ ├── NoteSyncCreatedAtTimeWithProperty.kt │ │ ├── NoteToggleFolding.kt │ │ ├── NoteToggleFoldingSubtree.kt │ │ ├── NoteUpdate.kt │ │ ├── NoteUpdateClockingState.kt │ │ ├── NoteUpdateContent.kt │ │ ├── NoteUpdateDeadlineTime.kt │ │ ├── NoteUpdateScheduledTime.kt │ │ ├── NoteUpdateState.kt │ │ ├── NoteUpdateStateDone.kt │ │ ├── NoteUpdateStateToggle.kt │ │ ├── RepoCreate.kt │ │ ├── RepoDelete.kt │ │ ├── RepoUpdate.kt │ │ ├── SavedSearchCreate.kt │ │ ├── SavedSearchDelete.kt │ │ ├── SavedSearchExport.kt │ │ ├── SavedSearchImport.kt │ │ ├── SavedSearchMoveDown.kt │ │ ├── SavedSearchMoveUp.kt │ │ ├── SavedSearchUpdate.kt │ │ ├── TimestampUpdate.kt │ │ ├── UseCase.kt │ │ ├── UseCaseResult.kt │ │ ├── UseCaseRunner.kt │ │ └── UseCaseWorker.kt │ │ ├── util │ │ ├── AgendaUtils.kt │ │ ├── AppPermissions.kt │ │ ├── BroadcastReceiverExt.kt │ │ ├── CircularArrayList.java │ │ ├── Encoding.kt │ │ ├── EncodingDetect.java │ │ ├── EventsInNote.kt │ │ ├── LogMajorEvents.kt │ │ ├── LogUtils.kt │ │ ├── MiscUtils.java │ │ ├── OrgFormatter.kt │ │ ├── SpaceTokenizer.java │ │ ├── UriUtils.java │ │ └── UserTimeFormatter.java │ │ └── widgets │ │ ├── ListWidgetProvider.java │ │ ├── ListWidgetSelectionActivity.kt │ │ ├── ListWidgetSelectionAdapter.kt │ │ ├── ListWidgetService.kt │ │ ├── WidgetColors.kt │ │ └── WidgetStyle.kt │ └── res │ ├── anim │ ├── fade_in.xml │ ├── fade_out.xml │ ├── fragment_enter.xml │ ├── fragment_exit.xml │ ├── rotate_counterclockwise.xml │ ├── slide_in_from_left.xml │ ├── slide_in_from_right.xml │ ├── slide_out_to_left.xml │ └── slide_out_to_right.xml │ ├── drawable-anydpi │ ├── cic_dropbox.xml │ ├── cic_git.xml │ ├── cic_logo_for_notification.xml │ ├── cic_logo_for_widget.xml │ ├── cic_new_above.xml │ ├── cic_new_below.xml │ ├── cic_new_under.xml │ ├── ic_abc.xml │ ├── ic_access_time.xml │ ├── ic_add.xml │ ├── ic_alarm.xml │ ├── ic_arrow_back.xml │ ├── ic_arrow_downward.xml │ ├── ic_arrow_drop_down.xml │ ├── ic_arrow_forward.xml │ ├── ic_arrow_upward.xml │ ├── ic_center_focus_strong.xml │ ├── ic_check_circle_outline.xml │ ├── ic_close.xml │ ├── ic_cloud_download_outline.xml │ ├── ic_cloud_outline.xml │ ├── ic_cloud_upload_outline.xml │ ├── ic_content_copy.xml │ ├── ic_content_cut.xml │ ├── ic_content_paste.xml │ ├── ic_create_new_folder.xml │ ├── ic_delete.xml │ ├── ic_done.xml │ ├── ic_edit.xml │ ├── ic_flag.xml │ ├── ic_folder_open.xml │ ├── ic_format_list_bulleted.xml │ ├── ic_help_outline.xml │ ├── ic_hourglass_bottom.xml │ ├── ic_hourglass_disabled.xml │ ├── ic_hourglass_empty.xml │ ├── ic_hourglass_top.xml │ ├── ic_info_outline.xml │ ├── ic_insert_drive_file.xml │ ├── ic_keyboard_arrow_down.xml │ ├── ic_keyboard_arrow_up.xml │ ├── ic_label_outline.xml │ ├── ic_language.xml │ ├── ic_library_books.xml │ ├── ic_link.xml │ ├── ic_menu.xml │ ├── ic_more_horiz.xml │ ├── ic_move_to_inbox.xml │ ├── ic_north.xml │ ├── ic_notes.xml │ ├── ic_notifications_none.xml │ ├── ic_open_in_new.xml │ ├── ic_palette.xml │ ├── ic_remove_red_eye.xml │ ├── ic_search.xml │ ├── ic_settings.xml │ ├── ic_share.xml │ ├── ic_snooze.xml │ ├── ic_south.xml │ ├── ic_south_east.xml │ ├── ic_star_border.xml │ ├── ic_storage.xml │ ├── ic_swap_vert.xml │ ├── ic_swipe_left.xml │ ├── ic_swipe_right.xml │ ├── ic_sync.xml │ ├── ic_sync_problem.xml │ ├── ic_today.xml │ ├── ic_unfold_more.xml │ ├── ic_warning.xml │ └── ic_widgets.xml │ ├── drawable │ ├── bullet.xml │ ├── bullet_folded.xml │ ├── cic_launcher_foreground.xml │ ├── cic_shortcut_new_note_foreground.xml │ ├── cic_shortcut_notebook_foreground.xml │ ├── cic_shortcut_sync_foreground.xml │ ├── fast_scroll_line.xml │ ├── fast_scroll_line_drawable.xml │ ├── fast_scroll_thumb.xml │ ├── fast_scroll_thumb_drawable.xml │ ├── image_placeholder.xml │ └── list_widget_preview.png │ ├── layout │ ├── activity_bookchooser.xml │ ├── activity_browser.xml │ ├── activity_list_widget_selection.xml │ ├── activity_logs.xml │ ├── activity_main.xml │ ├── activity_repo_directory.xml │ ├── activity_repo_dropbox.xml │ ├── activity_repo_git.xml │ ├── activity_repo_webdav.xml │ ├── activity_repos.xml │ ├── activity_settings.xml │ ├── activity_share.xml │ ├── dialog_book_delete.xml │ ├── dialog_book_rename.xml │ ├── dialog_certificates.xml │ ├── dialog_period_with_type.xml │ ├── dialog_progress_bar.xml │ ├── dialog_refile.xml │ ├── dialog_simple_one_liner.xml │ ├── dialog_spinner.xml │ ├── dialog_timestamp.xml │ ├── dialog_timestamp_title.xml │ ├── dialog_whats_new.xml │ ├── drawer_item_sync_failed.xml │ ├── drawer_item_sync_needed.xml │ ├── dropdown_item.xml │ ├── fragment_book.xml │ ├── fragment_book_preface.xml │ ├── fragment_books.xml │ ├── fragment_note.xml │ ├── fragment_query_agenda.xml │ ├── fragment_query_search.xml │ ├── fragment_saved_search.xml │ ├── fragment_saved_searches.xml │ ├── fragment_sync.xml │ ├── indent.xml │ ├── item_agenda_divider.xml │ ├── item_book.xml │ ├── item_browser.xml │ ├── item_head.xml │ ├── item_list_widget.xml │ ├── item_list_widget_divider.xml │ ├── item_list_widget_selection.xml │ ├── item_preface.xml │ ├── item_refile.xml │ ├── item_repo.xml │ ├── item_saved_search.xml │ ├── list_widget.xml │ ├── note_popup_button.xml │ ├── note_popup_buttons.xml │ ├── note_popup_pref_dialog.xml │ ├── note_popup_pref_dialog_divider_item.xml │ ├── note_popup_pref_dialog_item.xml │ ├── pref_dialog_states.xml │ ├── pref_dialog_time.xml │ ├── property.xml │ ├── rich_text.xml │ ├── spinner_item.xml │ └── text_list_item.xml │ ├── menu │ ├── book_actions.xml │ ├── book_cab_bottom.xml │ ├── book_cab_moving.xml │ ├── book_cab_top.xml │ ├── books_actions.xml │ ├── books_cab.xml │ ├── browser.xml │ ├── close_done.xml │ ├── done.xml │ ├── drawer.xml │ ├── logs_actions.xml │ ├── note_actions.xml │ ├── preface_actions.xml │ ├── query_actions.xml │ ├── query_cab_bottom.xml │ ├── query_cab_top.xml │ ├── repos_actions.xml │ ├── repos_cab.xml │ ├── saved_searches_actions.xml │ └── saved_searches_cab.xml │ ├── mipmap-anydpi-v26 │ ├── cic_launcher.xml │ ├── cic_shortcut_new_note.xml │ ├── cic_shortcut_notebook.xml │ └── cic_shortcut_sync.xml │ ├── mipmap-hdpi │ ├── cic_launcher.png │ ├── cic_shortcut_new_note.png │ ├── cic_shortcut_notebook.png │ └── cic_shortcut_sync.png │ ├── mipmap-mdpi │ ├── cic_launcher.png │ ├── cic_shortcut_new_note.png │ ├── cic_shortcut_notebook.png │ └── cic_shortcut_sync.png │ ├── mipmap-xhdpi │ ├── cic_launcher.png │ ├── cic_shortcut_new_note.png │ ├── cic_shortcut_notebook.png │ └── cic_shortcut_sync.png │ ├── mipmap-xxhdpi │ ├── cic_launcher.png │ ├── cic_shortcut_new_note.png │ ├── cic_shortcut_notebook.png │ └── cic_shortcut_sync.png │ ├── mipmap-xxxhdpi │ ├── cic_launcher.png │ ├── cic_shortcut_new_note.png │ ├── cic_shortcut_notebook.png │ └── cic_shortcut_sync.png │ ├── raw-cs-rCZ │ └── orgzly_getting_started.org │ ├── raw-de-rDE │ └── orgzly_getting_started.org │ ├── raw-es-rES │ └── orgzly_getting_started.org │ ├── raw-fr-rFR │ └── orgzly_getting_started.org │ ├── raw-hu-rHU │ └── orgzly_getting_started.org │ ├── raw-in-rID │ └── orgzly_getting_started.org │ ├── raw-it-rIT │ └── orgzly_getting_started.org │ ├── raw-ja-rJP │ └── orgzly_getting_started.org │ ├── raw-ko-rKR │ └── orgzly_getting_started.org │ ├── raw-nl-rNL │ └── orgzly_getting_started.org │ ├── raw-pl-rPL │ └── orgzly_getting_started.org │ ├── raw-pt-rBR │ └── orgzly_getting_started.org │ ├── raw-pt-rPT │ └── orgzly_getting_started.org │ ├── raw-ru-rRU │ └── orgzly_getting_started.org │ ├── raw-sv-rSE │ └── orgzly_getting_started.org │ ├── raw-tr-rTR │ └── orgzly_getting_started.org │ ├── raw-uk-rUA │ └── orgzly_getting_started.org │ ├── raw-zh-rCN │ └── orgzly_getting_started.org │ ├── raw-zh-rTW │ └── orgzly_getting_started.org │ ├── raw │ └── orgzly_getting_started.org │ ├── values-cs-rCZ │ └── strings.xml │ ├── values-de-rDE │ └── strings.xml │ ├── values-es-rES │ └── strings.xml │ ├── values-fr-rFR │ └── strings.xml │ ├── values-hu-rHU │ └── strings.xml │ ├── values-in-rID │ └── strings.xml │ ├── values-it-rIT │ └── strings.xml │ ├── values-ja-rJP │ └── strings.xml │ ├── values-ko-rKR │ └── strings.xml │ ├── values-night │ └── strings.xml │ ├── values-nl-rNL │ └── strings.xml │ ├── values-pl-rPL │ └── strings.xml │ ├── values-pt-rBR │ └── strings.xml │ ├── values-pt-rPT │ └── strings.xml │ ├── values-ru-rRU │ └── strings.xml │ ├── values-sv-rSE │ └── strings.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-tr-rTR │ └── strings.xml │ ├── values-uk-rUA │ └── strings.xml │ ├── values-v23 │ └── styles.xml │ ├── values-v28 │ └── styles.xml │ ├── values-v31 │ ├── prefs_keys.xml │ └── styles.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── arrays.xml │ ├── attrs.xml │ ├── cic_launcher_background.xml │ ├── cic_shortcut_new_note_background.xml │ ├── cic_shortcut_notebook_background.xml │ ├── cic_shortcut_sync_background.xml │ ├── colors.xml │ ├── dimens.xml │ ├── note_popup_ids.xml │ ├── prefs_keys.xml │ ├── strings.xml │ ├── strings_untranslatable.xml │ ├── styles.xml │ └── whats_new_strings.xml │ └── xml │ ├── backup_config.xml │ ├── file_paths.xml │ ├── list_widget_info.xml │ ├── network_security_config.xml │ ├── prefs.xml │ ├── prefs_screen_app.xml │ ├── prefs_screen_auto_sync.xml │ ├── prefs_screen_developer.xml │ ├── prefs_screen_look_and_feel.xml │ ├── prefs_screen_notebooks.xml │ ├── prefs_screen_notifications.xml │ ├── prefs_screen_org_file_format.xml │ ├── prefs_screen_org_mode_tags_indent.xml │ ├── prefs_screen_reminders.xml │ ├── prefs_screen_sync.xml │ ├── prefs_screen_widget.xml │ └── shortcuts.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── metadata ├── README.org └── en-US │ ├── changelogs │ └── 171.txt │ ├── full_description.txt │ ├── images │ ├── featureGraphic.png │ ├── icon.png │ └── phoneScreenshots │ │ ├── 01-drawer.png │ │ ├── 02-books.png │ │ ├── 03-book.png │ │ ├── 04-note.png │ │ ├── 05-searches.png │ │ ├── 06-agenda.png │ │ ├── 07-repos.png │ │ └── 08-dark.png │ ├── short_description.txt │ └── title.txt ├── sample.app.properties └── settings.gradle /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | - I have searched for existing issues that may be the same as or related to mine. 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'Type: bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | - I have searched for existing issues that may be the same as or related to mine. 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'Type: feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | - I have searched for existing issues that may be the same as or related to mine. 11 | -------------------------------------------------------------------------------- /.github/workflows/android-build-master.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'master' 7 | push: 8 | branches: 9 | - 'master' 10 | - 'release-*' 11 | 12 | jobs: 13 | build: 14 | name: Generate APK 15 | runs-on: ubuntu-22.04 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Setup JDK 20 | uses: actions/setup-java@v2 21 | with: 22 | distribution: 'zulu' 23 | java-version: '11' 24 | - name: Build APK 25 | run: ./gradlew assembleDebug 26 | - name: Upload APK 27 | uses: actions/upload-artifact@v2 28 | with: 29 | name: orgzly-debug-app 30 | path: '**/*.apk' 31 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/androidTest/assets/encoding/ascii.org: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | a b c 3 | 4 | Testing. 5 | -------------------------------------------------------------------------------- /app/src/androidTest/assets/encoding/few_chinese_characters.org: -------------------------------------------------------------------------------- 1 | 正體字/繁體字 2 | -------------------------------------------------------------------------------- /app/src/androidTest/assets/encoding/iso-8859-15-dos.org: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/androidTest/assets/encoding/iso-8859-15-dos.org -------------------------------------------------------------------------------- /app/src/androidTest/assets/encoding/org-blog-articles.org: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/androidTest/assets/encoding/org-blog-articles.org -------------------------------------------------------------------------------- /app/src/androidTest/assets/encoding/org-people.org: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/androidTest/assets/encoding/org-people.org -------------------------------------------------------------------------------- /app/src/androidTest/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/androidTest/assets/images/logo.png -------------------------------------------------------------------------------- /app/src/androidTest/assets/images/logo11w.org: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/androidTest/assets/images/logo11w.org -------------------------------------------------------------------------------- /app/src/androidTest/assets/lipsum/Japanese-Lipsum.org: -------------------------------------------------------------------------------- 1 | 平ろむ情崎フ由見分よぼく京報クあ移聴オメウホ供速は打来イネマ文夕メホタ地査月ご方更ム村何ユヲヤ洞厚ル権術ム初9町トク在攻哲控魅と。汽ぼ惜突ほしぜ幕空ー辞日5料いべむ事止じ浜刈んすそ内来傳ユヌ販2向ヒル一見すしフ大聞レルヤヨ泡水行ぱ四確おえぜ作伊記ヤチマ集融わくう。 2 | 3 | 応ヤ懐立レ存沖づ学東でよ禁天ごせ意記ウハユ著速大ぱじー参可記初重くまれず日究ニクネ辞朝域施ッわで。掲モ投応ヌセカロ意頼ト効曜黒ーた島経ラトもか肉傑い状改ぴリをゆ質3劇ヨムソ投検でけど試入すばゆラ権本ず治想康ふびなか整納運新申イごすぴ。第ん能長属ょ警育リソ常国ごク将会テ急町ヘヱネ流24光17光3横市ニケタ稿知ソ瀬太フメヨヌ調化航ラト地87開マクヌ言持院刈拒スあ。 4 | 5 | 策きぞぶふ化洋ろーゅト新女ナキカマ並互らぱあん生50梨ノ入立語力時談マウ権聞をっ来権っそあ率起つじを報挑発えおじる。文ヨチム権最対ミスチ情軍ナハレ日治たルあね町断フタ護店ア体71王ヱス品車カ来元み埼全底文ぐ市無アツ芸第ソヌイヤ足用こト浜効ょごめ敵4評定説号ぶしをほ。島むび謝億よげ城作独くえ系経づに制題ょと読来やゆン公2過フゆよ昇国チメサヘ読87小ヒ挑宝ス捕属負く。 6 | 7 | 拠ワセヤコ今読ねスうク伺76水処27症ごれぜス賞相あべゅげ失23売かぼド興用らかっフ補今もドで墓患督ドねッす布前答徴んひわ覧盤主達をくや。定しぴじ展各メキ役手ヤノシカ中理サヱ並突憾わ樹動ケ聞周葉フき回懸モホ名産条ヤ先大メヘ報票ょ入王予図ゅばぐ必彼精争効べひ。棋サロ移由ヨ急逢ッ悟策ウクハヘ作裁そ載却トサ以4読マヘ利弘げすほが聞右4通ゅ属振アラオ留寄ワウケナ底宅ぎでわ枝億ゃ。 8 | 9 | 拠ルぶ意市コニレ革88形ラ和霧サ企紀ろぐ連業りぶろ齢勝ゃラびづ乱利ソナタア法野ホイ売伸矛ればとお思6集12質よそ似既杉賢路ほー。賀モ属風のぶたご支送ヨロレウ野台にてばも思断くはめ温47拠ヒト石弾ゆすほ通量べへ選団反はまほ後前キ臓人本り合個る対描レオ各丹庄こずだの。新メ臓年札ね協職夫球んめさフ集意ンイか陣賞ルト局察京ソウヒ馬覧ルサヘメ北形クヨ雪経スつじや会週卒ゃ。 -------------------------------------------------------------------------------- /app/src/androidTest/java/com/orgzly/android/OrgzlyTestRunner.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import androidx.test.runner.AndroidJUnitRunner 6 | 7 | class OrgzlyTestRunner : AndroidJUnitRunner() { 8 | 9 | /** 10 | * Uses [AppUnderTest] instead of [App]. 11 | */ 12 | @Throws(InstantiationException::class, IllegalAccessException::class, ClassNotFoundException::class) 13 | override fun newApplication(cl: ClassLoader, className: String, context: Context): Application { 14 | return super.newApplication(cl, AppUnderTest::class.java.name, context) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/orgzly/android/misc/LogSomethingNotTest.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.misc 2 | 3 | import android.os.Environment 4 | import android.util.Log 5 | import com.orgzly.android.OrgzlyTest 6 | import org.junit.Test 7 | 8 | class LogSomethingNotTest : OrgzlyTest() { 9 | @Test 10 | fun testLink() { 11 | Log.i( 12 | TAG, String.format( 13 | """ 14 | Environment.getExternalStorageDirectory: %s 15 | context.filesDir: %s 16 | context.getExternalFilesDir(null): %s 17 | context.getExternalFilesDir(DOWNLOADS): %s""".trimIndent(), 18 | Environment.getExternalStorageDirectory(), 19 | context.filesDir, 20 | context.getExternalFilesDir(null), 21 | context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) 22 | ) 23 | ) 24 | } 25 | 26 | companion object { 27 | private val TAG = BookParsingTest::class.java.name 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/orgzly/android/ui/ImageLoaderTest.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | import org.junit.Assert.* 4 | import org.junit.Test 5 | 6 | 7 | class ImageLoaderTest { 8 | 9 | @Test 10 | fun hasSupportedExtension() { 11 | assertTrue(ImageLoader.hasSupportedExtension("file.png")) 12 | assertTrue(ImageLoader.hasSupportedExtension("file.PNG")) 13 | assertTrue(ImageLoader.hasSupportedExtension("../file.png")) 14 | assertTrue(ImageLoader.hasSupportedExtension("dir/file.png")) 15 | 16 | assertFalse(ImageLoader.hasSupportedExtension("png")) 17 | assertFalse(ImageLoader.hasSupportedExtension(".png")) 18 | assertFalse(ImageLoader.hasSupportedExtension("filepng")) 19 | assertFalse(ImageLoader.hasSupportedExtension("dir.png/file")) 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/orgzly/android/usecase/NoteUpdateDeadlineTimeTest.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.OrgzlyTest 4 | import com.orgzly.android.repos.RepoType 5 | import com.orgzly.org.datetime.OrgDateTime 6 | import org.junit.Assert.* 7 | import org.junit.Test 8 | 9 | class NoteUpdateDeadlineTimeTest : OrgzlyTest() { 10 | @Test 11 | fun book_markedAsModified() { 12 | testUtils.setupBook("book", "* Note") 13 | testUtils.setupRepo(RepoType.MOCK, "mock://repo-a") 14 | testUtils.sync() 15 | 16 | assertFalse(dataRepository.getBook("book")!!.isModified) 17 | assertNull(dataRepository.getBook("book")!!.mtime) 18 | 19 | UseCaseRunner.run(NoteUpdateDeadlineTime( 20 | setOf(dataRepository.getLastNote("Note")!!.id), 21 | OrgDateTime(true))) 22 | 23 | assertTrue(dataRepository.getBook("book")!!.isModified) 24 | assertTrue(dataRepository.getBook("book")!!.mtime!! > 0) 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/orgzly/android/usecase/NoteUpdateScheduledTimeTest.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.OrgzlyTest 4 | import com.orgzly.android.repos.RepoType 5 | import com.orgzly.org.datetime.OrgDateTime 6 | import org.junit.Assert.* 7 | import org.junit.Test 8 | 9 | class NoteUpdateScheduledTimeTest : OrgzlyTest() { 10 | @Test 11 | fun book_markedAsModified() { 12 | testUtils.setupBook("book", "* Note") 13 | testUtils.setupRepo(RepoType.MOCK, "mock://repo-a") 14 | testUtils.sync() 15 | 16 | assertFalse(dataRepository.getBook("book")!!.isModified) 17 | assertNull(dataRepository.getBook("book")!!.mtime) 18 | 19 | UseCaseRunner.run(NoteUpdateScheduledTime( 20 | setOf(dataRepository.getLastNote("Note")!!.id), 21 | OrgDateTime(true))) 22 | 23 | assertTrue(dataRepository.getBook("book")!!.isModified) 24 | assertTrue(dataRepository.getBook("book")!!.mtime!! > 0) 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/cic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/main/cic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ActionReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.orgzly.android.AppIntent.ACTION_SYNC_START 7 | import com.orgzly.android.AppIntent.ACTION_SYNC_STOP 8 | import com.orgzly.android.sync.SyncRunner 9 | 10 | class ActionReceiver : BroadcastReceiver() { 11 | override fun onReceive(context: Context, receivedIntent: Intent) { 12 | when (receivedIntent.action) { 13 | ACTION_SYNC_START -> { 14 | SyncRunner.startSync(); 15 | } 16 | 17 | ACTION_SYNC_STOP -> { 18 | SyncRunner.stopSync(); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/BookFormat.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android; 2 | 3 | public enum BookFormat { 4 | ORG 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/BootCompletedReceiver.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import com.orgzly.BuildConfig; 7 | import com.orgzly.android.prefs.AppPreferences; 8 | import com.orgzly.android.ui.notifications.Notifications; 9 | import com.orgzly.android.util.LogUtils; 10 | 11 | public class BootCompletedReceiver extends BroadcastReceiver { 12 | public static final String TAG = BootCompletedReceiver.class.getName(); 13 | 14 | @Override 15 | public void onReceive(Context context, Intent intent) { 16 | if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, context, intent); 17 | 18 | if (intent != null && Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { 19 | if (AppPreferences.newNoteNotification(context)) { 20 | Notifications.showOngoingNotification(context); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/data/logs/AppLogsRepository.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.data.logs 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | 5 | interface AppLogsRepository { 6 | fun log(type: String, str: String) 7 | 8 | fun getFlow(type: String): Flow> 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/data/logs/LogEntry.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.data.logs 2 | 3 | data class LogEntry(val time: Long, val type: String, val message: String) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/AppLogDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.AppLog 6 | import kotlinx.coroutines.flow.Flow 7 | 8 | @Dao 9 | abstract class AppLogDao : BaseDao { 10 | @Query("SELECT * FROM app_logs WHERE name = :name ORDER BY timestamp") 11 | abstract fun getFlow(name: String): Flow> 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/BookLinkDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.* 4 | import com.orgzly.android.db.entity.BookLink 5 | 6 | @Dao 7 | abstract class BookLinkDao : BaseDao { 8 | @Query("SELECT * FROM book_links WHERE book_id = :bookId") 9 | abstract fun getByBookId(bookId: Long): BookLink? 10 | 11 | @Insert(onConflict = OnConflictStrategy.REPLACE) 12 | abstract fun replace(bookLink: BookLink): Long 13 | 14 | @Query("DELETE FROM book_links WHERE book_id = :bookId") 15 | abstract fun deleteByBookId(bookId: Long) 16 | 17 | @Query("DELETE FROM book_links WHERE repo_id = :repoId") 18 | abstract fun deleteByRepoId(repoId: Long) 19 | 20 | @Transaction 21 | open fun upsert(bookId: Long, repoId: Long) { 22 | val link = getByBookId(bookId) 23 | 24 | if (link == null) { 25 | insert(BookLink(bookId, repoId)) 26 | } else { 27 | update(link.copy(repoId = repoId)) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/BookSyncDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.* 4 | import com.orgzly.android.db.entity.BookSync 5 | 6 | @Dao 7 | interface BookSyncDao : BaseDao { 8 | @Query("SELECT * FROM book_syncs WHERE book_id = :bookId") 9 | fun get(bookId: Long): BookSync? 10 | 11 | @Transaction 12 | fun upsert(bookId: Long, versionedRookId: Long) { 13 | val sync = get(bookId) 14 | 15 | if (sync == null) { 16 | insert(BookSync(bookId, versionedRookId)) 17 | } else { 18 | update(sync.copy(versionedRookId = versionedRookId)) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/DbRepoBookDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.DbRepoBook 6 | 7 | @Dao 8 | interface DbRepoBookDao : BaseDao { 9 | @Query("SELECT * FROM db_repo_books WHERE url = :url") 10 | fun getByUrl(url: String): DbRepoBook? 11 | 12 | @Query("SELECT * FROM db_repo_books WHERE repo_url = :repoUrl") 13 | fun getAllByRepo(repoUrl: String): List 14 | 15 | @Query("DELETE FROM db_repo_books WHERE url = :url") 16 | fun deleteByUrl(url: String): Int 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/NoteEventDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.NoteEvent 6 | 7 | @Dao 8 | abstract class NoteEventDao : BaseDao { 9 | @Query("SELECT * FROM note_events WHERE note_id = :noteId") 10 | abstract fun get(noteId: Long): List 11 | 12 | @Query("DELETE FROM note_events WHERE note_id = :noteId") 13 | abstract fun deleteForNote(noteId: Long) 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/OrgRangeDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.OrgRange 6 | 7 | @Dao 8 | interface OrgRangeDao : BaseDao { 9 | @Query("SELECT * FROM org_ranges WHERE string = :str") 10 | fun getByString(str: String): OrgRange? 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/OrgTimestampDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.OrgTimestamp 6 | 7 | @Dao 8 | interface OrgTimestampDao : BaseDao { 9 | @Query("SELECT * FROM org_timestamps") 10 | fun getAll(): List 11 | 12 | @Query("SELECT * FROM org_timestamps WHERE string = :str") 13 | fun getByString(str: String): OrgTimestamp? 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/RookDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.Rook 6 | 7 | @Dao 8 | abstract class RookDao : BaseDao { 9 | @Query("SELECT * FROM rooks WHERE repo_id = :repoId AND rook_url_id = :rookUrlId") 10 | abstract fun get(repoId: Long, rookUrlId: Long): Rook? 11 | 12 | fun getOrInsert(repoId: Long, rookUrlId: Long): Long = 13 | get(repoId, rookUrlId).let { 14 | it?.id ?: insert(Rook(0, repoId, rookUrlId)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/RookUrlDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.orgzly.android.db.entity.RookUrl 6 | 7 | @Dao 8 | abstract class RookUrlDao : BaseDao { 9 | @Query("SELECT * FROM rook_urls WHERE url = :url") 10 | abstract fun get(url: String): RookUrl? 11 | 12 | fun getOrInsert(rookUrl: String): Long = 13 | get(rookUrl).let { 14 | it?.id ?: insert(RookUrl(0, rookUrl)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/dao/VersionedRookDao.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.OnConflictStrategy 6 | import com.orgzly.android.db.entity.VersionedRook 7 | 8 | @Dao 9 | abstract class VersionedRookDao : BaseDao { 10 | @Insert(onConflict = OnConflictStrategy.REPLACE) 11 | abstract fun replace(rook: VersionedRook): Long 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/AppLog.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.Entity 4 | import androidx.room.Index 5 | import androidx.room.PrimaryKey 6 | 7 | @Entity( 8 | tableName = "app_logs", 9 | 10 | indices = [ 11 | Index("timestamp"), 12 | Index("name") 13 | ] 14 | ) 15 | data class AppLog( 16 | @PrimaryKey(autoGenerate = true) 17 | 18 | val id: Long, 19 | 20 | val timestamp: Long, 21 | 22 | val name: String, 23 | 24 | val message: String 25 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/BookAction.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.Entity 4 | 5 | /** 6 | * Last action performed on a notebook. 7 | * 8 | * Action can be a result of renaming, syncing (loading, saving, ...), importing, etc. 9 | */ 10 | data class BookAction( 11 | val type: Type, 12 | val message: String, 13 | val timestamp: Long 14 | ) { 15 | enum class Type { 16 | INFO, 17 | ERROR, 18 | PROGRESS 19 | } 20 | 21 | companion object { 22 | @JvmStatic 23 | fun forNow(type: Type, message: String): BookAction { 24 | return BookAction(type, message, System.currentTimeMillis()) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/BookLink.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "book_links", 7 | 8 | foreignKeys = [ 9 | ForeignKey( 10 | entity = Book::class, 11 | parentColumns = arrayOf("id"), 12 | childColumns = arrayOf("book_id"), 13 | onDelete = ForeignKey.CASCADE), 14 | ForeignKey( 15 | entity = Repo::class, 16 | parentColumns = arrayOf("id"), 17 | childColumns = arrayOf("repo_id"), 18 | onDelete = ForeignKey.CASCADE) 19 | ], 20 | 21 | indices = [ 22 | Index("repo_id") 23 | ] 24 | ) 25 | data class BookLink( 26 | @PrimaryKey 27 | @ColumnInfo(name = "book_id") 28 | val bookId: Long, 29 | 30 | @ColumnInfo(name = "repo_id") 31 | val repoId: Long 32 | ) 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/BookSync.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "book_syncs", 7 | 8 | foreignKeys = [ 9 | ForeignKey( 10 | entity = Book::class, 11 | parentColumns = arrayOf("id"), 12 | childColumns = arrayOf("book_id"), 13 | onDelete = ForeignKey.CASCADE), 14 | ForeignKey( 15 | entity = VersionedRook::class, 16 | parentColumns = arrayOf("id"), 17 | childColumns = arrayOf("versioned_rook_id"), 18 | onDelete = ForeignKey.CASCADE) 19 | ], 20 | 21 | indices = [ 22 | Index("versioned_rook_id") 23 | ] 24 | ) 25 | data class BookSync( 26 | @PrimaryKey 27 | @ColumnInfo(name = "book_id") 28 | val bookId: Long, 29 | 30 | @ColumnInfo(name = "versioned_rook_id") 31 | val versionedRookId: Long 32 | ) 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/BookView.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.Embedded 4 | import com.orgzly.android.repos.VersionedRook 5 | 6 | data class BookView( 7 | @Embedded 8 | val book: Book, 9 | 10 | val noteCount: Int, 11 | 12 | @Embedded(prefix = "link_repo_") 13 | val linkRepo: Repo? = null, 14 | 15 | @Embedded(prefix = "synced_to_") 16 | val syncedTo: VersionedRook? = null 17 | ) { 18 | fun hasLink(): Boolean { 19 | return linkRepo != null 20 | } 21 | 22 | fun hasSync(): Boolean { 23 | return syncedTo != null 24 | } 25 | 26 | fun isOutOfSync(): Boolean { 27 | return syncedTo != null && book.isModified 28 | } 29 | 30 | fun isModified(): Boolean { 31 | return book.isModified 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/DbRepoBook.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "db_repo_books", 7 | 8 | indices = [ 9 | Index("repo_url", "url", unique = true) 10 | ] 11 | ) 12 | data class DbRepoBook( 13 | @PrimaryKey(autoGenerate = true) 14 | val id: Long, 15 | 16 | @ColumnInfo(name = "repo_url") 17 | val repoUrl: String, 18 | 19 | val url: String, 20 | 21 | val revision: String, 22 | 23 | val mtime: Long, 24 | 25 | val content: String, 26 | 27 | @ColumnInfo(name = "created_at") 28 | val createdAt: Long 29 | ) 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/NoteProperty.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "note_properties", 7 | 8 | primaryKeys = [ "note_id", "position" ], 9 | 10 | foreignKeys = [ 11 | ForeignKey( 12 | entity = Note::class, 13 | parentColumns = arrayOf("id"), 14 | childColumns = arrayOf("note_id"), 15 | onDelete = ForeignKey.CASCADE) 16 | ], 17 | 18 | indices = [ 19 | Index("note_id"), 20 | Index("position"), 21 | Index("name"), 22 | Index("value") 23 | ] 24 | ) 25 | data class NoteProperty( 26 | @ColumnInfo(name = "note_id") 27 | val noteId: Long, 28 | 29 | val position: Int, 30 | 31 | val name: String, 32 | 33 | val value: String 34 | ) 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/Repo.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | import com.orgzly.android.repos.RepoType 5 | 6 | @Entity( 7 | tableName = "repos", 8 | 9 | indices = [ 10 | Index("url", unique = true) 11 | ] 12 | ) 13 | data class Repo( 14 | @PrimaryKey(autoGenerate = true) 15 | val id: Long, 16 | 17 | val type: RepoType, 18 | 19 | val url: String 20 | ) { 21 | override fun toString(): String { 22 | return url 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/RookUrl.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "rook_urls", 7 | 8 | indices = [ 9 | Index("url", unique = true) 10 | ] 11 | ) 12 | data class RookUrl( 13 | @PrimaryKey(autoGenerate = true) 14 | val id: Long, 15 | 16 | val url: String 17 | ) 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/SavedSearch.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "searches" 7 | ) 8 | data class SavedSearch( 9 | @PrimaryKey(autoGenerate = true) 10 | val id: Long, 11 | 12 | val name: String, 13 | 14 | val query: String, 15 | 16 | val position: Int 17 | ) { 18 | fun areContentsTheSame(that: SavedSearch): Boolean { 19 | return name == that.name && query == that.query && position == that.position 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/db/entity/VersionedRook.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.db.entity 2 | 3 | import androidx.room.* 4 | 5 | @Entity( 6 | tableName = "versioned_rooks", 7 | 8 | foreignKeys = [ 9 | ForeignKey( 10 | entity = Rook::class, 11 | parentColumns = arrayOf("id"), 12 | childColumns = arrayOf("rook_id"), 13 | onDelete = ForeignKey.CASCADE) 14 | ], 15 | 16 | indices = [ 17 | Index("rook_id") 18 | ] 19 | ) 20 | data class VersionedRook( 21 | @PrimaryKey(autoGenerate = true) 22 | val id: Long, 23 | 24 | @ColumnInfo(name = "rook_id") 25 | val rookId: Long, 26 | 27 | @ColumnInfo(name = "rook_revision") 28 | val rookRevision: String, 29 | 30 | @ColumnInfo(name = "rook_mtime") 31 | val rookMtime: Long 32 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/di/module/DatabaseModule.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.di.module 2 | 3 | import android.content.Context 4 | import com.orgzly.android.db.OrgzlyDatabase 5 | import dagger.Module 6 | import dagger.Provides 7 | import javax.inject.Singleton 8 | 9 | @Module 10 | internal class DatabaseModule(val testing: Boolean = false) { 11 | @Provides 12 | @Singleton 13 | internal fun provideDatabase(context: Context): OrgzlyDatabase { 14 | return if (testing) { 15 | OrgzlyDatabase.forFile(context, OrgzlyDatabase.NAME_FOR_TESTS) 16 | // return OrgzlyDatabase.forMemory(context) 17 | } else { 18 | OrgzlyDatabase.forFile(context, OrgzlyDatabase.NAME) 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/git/GitPreferences.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.git; 2 | 3 | import android.net.Uri; 4 | 5 | public interface GitPreferences { 6 | GitTransportSetter createTransportSetter(); 7 | 8 | String getAuthor(); 9 | 10 | String getEmail(); 11 | 12 | String repositoryFilepath(); 13 | 14 | String remoteName(); 15 | 16 | String branchName(); 17 | 18 | Uri remoteUri(); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/git/GitTransportSetter.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.git; 2 | 3 | import org.eclipse.jgit.api.TransportCommand; 4 | 5 | public interface GitTransportSetter { 6 | public TransportCommand setTransport(TransportCommand tc); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/git/HTTPSTransportSetter.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.git; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import org.eclipse.jgit.api.TransportCommand; 6 | import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; 7 | 8 | public class HTTPSTransportSetter implements GitTransportSetter { 9 | private String username; 10 | private String password; 11 | 12 | public HTTPSTransportSetter(@NonNull String username, @NonNull String password) { 13 | this.username = username; 14 | this.password = password; 15 | } 16 | 17 | public TransportCommand setTransport(TransportCommand tc) { 18 | tc.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)); 19 | return tc; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/prefs/AppPreferencesValues.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.prefs; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Values of all shared preferences. 7 | * 8 | * Used by {@code OrgzlyTest} for restoring the preferences. 9 | */ 10 | public class AppPreferencesValues { 11 | Map defaultPrefsValues; 12 | Map statePrefsValues; 13 | Map reposPrefsValues; 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/prefs/StateWorkflows.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.prefs; 2 | 3 | import com.orgzly.org.OrgStatesWorkflow; 4 | import com.orgzly.org.OrgStringUtils; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * List of {@link OrgStatesWorkflow}s 10 | */ 11 | public class StateWorkflows extends ArrayList { 12 | public StateWorkflows(String s) { 13 | if (s == null) { 14 | return; 15 | } 16 | 17 | String st = s.trim(); 18 | 19 | if (st.length() == 0) { 20 | return; 21 | } 22 | 23 | for (String line: st.split("\n+")) { 24 | add(new OrgStatesWorkflow(line)); 25 | } 26 | } 27 | 28 | public String toString() { 29 | return OrgStringUtils.join(this, "\n"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/Options.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query 2 | 3 | data class Options(val agendaDays: Int = 0) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/Query.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query 2 | 3 | data class Query @JvmOverloads constructor( 4 | val condition: Condition?, 5 | val sortOrders: List = listOf(), 6 | val options: Options = Options()) { 7 | 8 | fun isAgenda(): Boolean = options.agendaDays > 0 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/Relation.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query 2 | 3 | enum class Relation { 4 | EQ, // equal to 5 | NE, // not equal to 6 | LT, // less than 7 | LE, // less than or equal to 8 | GT, // greater than 9 | GE // greater than or equal to 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/SortOrder.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query 2 | 3 | sealed class SortOrder { 4 | abstract val desc: Boolean 5 | 6 | data class Book(override val desc: Boolean = false) : SortOrder() 7 | data class Title(override val desc: Boolean = false) : SortOrder() 8 | data class Scheduled(override val desc: Boolean = false) : SortOrder() 9 | data class Deadline(override val desc: Boolean = false) : SortOrder() 10 | data class Event(override val desc: Boolean = false) : SortOrder() 11 | data class Closed(override val desc: Boolean = false) : SortOrder() 12 | data class Created(override val desc: Boolean = false) : SortOrder() 13 | data class Priority(override val desc: Boolean = false) : SortOrder() 14 | data class State(override val desc: Boolean = false) : SortOrder() 15 | data class Position(override val desc: Boolean = false) : SortOrder() 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/StateType.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query 2 | 3 | enum class StateType { TODO, DONE, NONE } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/sql/SqlQuery.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query.sql 2 | 3 | data class SqlQuery( 4 | val selection: String, 5 | val selectionArgs: List, 6 | val having: String, 7 | val orderBy: String) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/user/InternalQueryBuilder.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query.user 2 | 3 | class InternalQueryBuilder : DottedQueryBuilder() -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/query/user/InternalQueryParser.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.query.user 2 | 3 | class InternalQueryParser : DottedQueryParser() -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/reminders/NoteReminder.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.reminders 2 | 3 | import org.joda.time.DateTime 4 | 5 | data class NoteReminder(val runTime: DateTime, val payload: NoteReminderPayload) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/reminders/NoteReminderPayload.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.reminders 2 | 3 | import com.orgzly.org.datetime.OrgDateTime 4 | 5 | data class NoteReminderPayload( 6 | var noteId: Long, 7 | var bookId: Long, 8 | var bookName: String, 9 | var title: String, 10 | var timeType: Int, 11 | var orgDateTime: OrgDateTime 12 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/RepoType.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos 2 | 3 | import java.lang.IllegalArgumentException 4 | 5 | enum class RepoType(val id: Int) { 6 | MOCK(1), 7 | DROPBOX(2), 8 | DIRECTORY(3), 9 | DOCUMENT(4), 10 | WEBDAV(5), 11 | GIT(6); 12 | 13 | companion object { 14 | @JvmStatic 15 | fun fromId(type: Int): RepoType { 16 | return when (type) { 17 | 1 -> MOCK 18 | 2 -> DROPBOX 19 | 3 -> DIRECTORY 20 | 4 -> DOCUMENT 21 | 5 -> WEBDAV 22 | 6 -> GIT 23 | 24 | else -> throw IllegalArgumentException("Unknown repo type id $type") 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/RepoUtils.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos; 2 | 3 | import java.util.Collection; 4 | 5 | public class RepoUtils { 6 | /** 7 | * @return true if there is a repository that requires connection, false otherwise 8 | */ 9 | public static boolean isConnectionRequired(Collection repos) { 10 | for (SyncRepo repo: repos) { 11 | if (repo.isConnectionRequired()) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | 18 | /** 19 | * @return true if all repositories support auto-sync, false otherwise 20 | */ 21 | public static boolean isAutoSyncSupported(Collection repos) { 22 | for (SyncRepo repo: repos) { 23 | if (!repo.isAutoSyncSupported()) { 24 | return false; 25 | } 26 | } 27 | return true; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/RepoWithProps.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos 2 | 3 | import com.orgzly.android.db.entity.Repo 4 | 5 | data class RepoWithProps @JvmOverloads constructor( 6 | val repo: Repo, 7 | val props: Map = emptyMap()) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/TwoWaySyncRepo.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos 2 | 3 | import android.net.Uri 4 | import java.io.File 5 | import java.io.IOException 6 | 7 | interface TwoWaySyncRepo { 8 | @Throws(IOException::class) 9 | fun syncBook(uri: Uri, current: VersionedRook?, fromDB: File): TwoWaySyncResult 10 | 11 | fun tryPushIfHeadDiffersFromRemote() 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/TwoWaySyncResult.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos 2 | 3 | import org.jetbrains.annotations.NotNull 4 | import org.jetbrains.annotations.Nullable 5 | import java.io.File 6 | 7 | /** 8 | * Result of doing a two-way synchronization. 9 | * @param newRook The new versioned book that was created by this synchronization operation 10 | * @param loadFile This file contains the new data that should be loaded to the local notebook that 11 | * was just synchronized. When it is null there's no new information to load, meaning that the 12 | * current contents of the notebook are up to date. 13 | * @param onMainBranch Boolean indicating whether the sync resulted in a commit on the main branch, 14 | * or on a temporary branch. 15 | * @see GitRepo Which implements [TwoWaySyncRepo] 16 | * @see TwoWaySyncRepo 17 | */ 18 | data class TwoWaySyncResult(val newRook: @NotNull VersionedRook, val onMainBranch: Boolean, val loadFile: @Nullable File?) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/repos/VersionedRook.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.repos 2 | 3 | import android.net.Uri 4 | 5 | class VersionedRook( 6 | repoId: Long, 7 | repoType: RepoType, 8 | repoUri: Uri, 9 | uri: Uri, 10 | val revision: String, 11 | val mtime: Long 12 | ) : Rook(repoId, repoType, repoUri, uri) { 13 | 14 | constructor(rook: Rook, revision: String, mtime: Long) : 15 | this(rook.repoId, rook.repoType, rook.getRepoUri(), rook.getUri(), revision, mtime) 16 | 17 | override fun toString(): String { 18 | return uri.buildUpon() 19 | .appendQueryParameter("revision", revision) 20 | .appendQueryParameter("mtime", mtime.toString()) 21 | .build().toString() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/savedsearch/SavedSearchStore.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.savedsearch 2 | 3 | import android.net.Uri 4 | 5 | interface SavedSearchStore { 6 | fun importSearches(uri: Uri): Int 7 | 8 | fun exportSearches(uri: Uri?): Int 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/AgendaTimeType.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | data class AgendaTimeType( 4 | val timeType: TimeType, 5 | val isWarning: Boolean = false, 6 | val overdueDays: Int = 0) -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/AppBar.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | class AppBar(var modes: Map) { 4 | 5 | val mode: SingleLiveEvent = SingleLiveEvent() 6 | 7 | fun toModeFromSelectionCount(count: Int) { 8 | if (count == 0) { 9 | // No selection, default mode 10 | mode.postValue(0) 11 | } else { 12 | if (mode.value == 0) { 13 | // Selection, from default mode 14 | mode.postValue(1) 15 | } else { 16 | // Keep mode 17 | mode.postValue(mode.value) 18 | } 19 | } 20 | } 21 | 22 | fun toMode(id: Int) { 23 | this.mode.postValue(id) 24 | } 25 | 26 | fun handleOnBackPressed() { 27 | mode.value?.let { currentMode -> 28 | val previousMode = modes[currentMode] 29 | if (previousMode != null) { 30 | toMode(previousMode) 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/CommonViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | open class CommonViewModel : ViewModel() { 6 | val snackBarMessage: SingleLiveEvent = SingleLiveEvent() 7 | 8 | val errorEvent: SingleLiveEvent = SingleLiveEvent() 9 | 10 | fun catchAndPostError(action: () -> Unit) { 11 | try { 12 | action() 13 | } catch (e: Throwable) { 14 | e.printStackTrace() 15 | errorEvent.postValue(e) 16 | } 17 | } 18 | 19 | override fun onCleared() { 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/LauncherActivity.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.orgzly.BuildConfig 7 | import com.orgzly.android.ui.main.MainActivity 8 | import com.orgzly.android.util.LogUtils 9 | 10 | class LauncherActivity : AppCompatActivity() { 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | 14 | if (BuildConfig.LOG_DEBUG) 15 | LogUtils.d(TAG, intent, savedInstanceState) 16 | 17 | startActivity(Intent(this, MainActivity::class.java)) 18 | // startActivity(Intent(this, IntroActivity::class.java)) 19 | 20 | finish() 21 | } 22 | 23 | companion object { 24 | private val TAG = LauncherActivity::class.java.name 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/NotePriorities.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | import android.content.Context 4 | import com.orgzly.android.prefs.AppPreferences 5 | import java.util.* 6 | 7 | class NotePriorities { 8 | private val values = ArrayList() 9 | 10 | val array: Array 11 | get() = values.toTypedArray() 12 | 13 | fun indexOf(keyword: String) = values.indexOf(keyword) 14 | 15 | operator fun get(i: Int) = values[i] 16 | 17 | companion object { 18 | @JvmStatic 19 | fun fromPreferences(context: Context): NotePriorities { 20 | val obj = NotePriorities() 21 | 22 | val lastPriority = AppPreferences.minPriority(context) 23 | 24 | require(lastPriority != null && lastPriority.length == 1) { 25 | "Last priority must be a character, not $lastPriority" 26 | } 27 | 28 | 'A'.rangeTo(lastPriority[0]).forEach { p -> obj.values.add(p.toString()) } 29 | 30 | return obj 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/OnViewHolderClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | import android.view.View 4 | 5 | interface OnViewHolderClickListener { 6 | fun onClick(view: View, position: Int, item: T) 7 | fun onLongClick(view: View, position: Int, item: T) 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/Place.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui; 2 | 3 | /** 4 | * Various actions can be performed relative to the specific item. 5 | * E.g., new note can be created *under* another, pasted *below*, etc. 6 | */ 7 | public enum Place { 8 | ABOVE, 9 | UNDER, 10 | UNDER_AS_FIRST, 11 | BELOW, 12 | UNSPECIFIED 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/SelectableItemAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | interface SelectableItemAdapter { 4 | fun getSelection(): Selection 5 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/SyncShortcutActivity.java: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | import com.orgzly.android.sync.SyncRunner; 8 | 9 | /** 10 | * Activity started by the Sync app shortcut. 11 | * App shortcuts require Intents that start activities, so this is used to start 12 | * syncing without opening the app. 13 | */ 14 | public class SyncShortcutActivity extends AppCompatActivity { 15 | @Override 16 | public void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | SyncRunner.startSync(); 19 | finish(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/TimeType.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui 2 | 3 | enum class TimeType { 4 | SCHEDULED, 5 | DEADLINE, 6 | EVENT, 7 | CLOSED, 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/books/BooksViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.books 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class BooksViewModelFactory(private val dataRepository: DataRepository) : ViewModelProvider.Factory { 8 | override fun create(modelClass: Class): T { 9 | @Suppress("UNCHECKED_CAST") 10 | return BooksViewModel(dataRepository) as T 11 | } 12 | 13 | companion object { 14 | fun getInstance(dataRepository: DataRepository): ViewModelProvider.Factory { 15 | return BooksViewModelFactory(dataRepository) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/dialogs/TimestampDialogViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.dialogs 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.ui.TimeType 6 | 7 | class TimestampDialogViewModelFactory( 8 | private val timeType: TimeType, 9 | private val orgDateTime: String? 10 | ) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return TimestampDialogViewModel(timeType, orgDateTime) as T 15 | } 16 | 17 | companion object { 18 | fun getInstance(timeType: TimeType, orgDateTime: String?): ViewModelProvider.Factory { 19 | return TimestampDialogViewModelFactory(timeType, orgDateTime) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/dndrv/ItemTouchHelperAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.dndrv 2 | 3 | interface ItemTouchHelperAdapter { 4 | fun onItemMove(fromPosition: Int, toPosition: Int): Boolean 5 | 6 | fun onItemDismiss(position: Int) 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/dndrv/ItemTouchHelperViewHolder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.orgzly.android.ui.dndrv 17 | 18 | interface ItemTouchHelperViewHolder { 19 | fun onItemSelected() 20 | 21 | fun onItemClear() 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/dndrv/OnStartDragListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.orgzly.android.ui.dndrv 17 | 18 | import androidx.recyclerview.widget.RecyclerView 19 | 20 | fun interface OnStartDragListener { 21 | fun onStartDrag(viewHolder: RecyclerView.ViewHolder) 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/drawer/DrawerItem.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.drawer 2 | 3 | /** 4 | * Implemented by fragments opened using the drawer. 5 | * 6 | * Used to flag (check) [android.view.MenuItem] active fragment in the drawer. 7 | */ 8 | interface DrawerItem { 9 | fun getCurrentDrawerItemId(): String 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/logs/AppLogsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.logs 2 | 3 | import com.orgzly.android.data.logs.AppLogsRepository 4 | import com.orgzly.android.ui.CommonViewModel 5 | import com.orgzly.android.util.LogMajorEvents 6 | import kotlinx.coroutines.flow.map 7 | import java.util.* 8 | 9 | class AppLogsViewModel(appLogsRepository: AppLogsRepository) : CommonViewModel() { 10 | val logs = appLogsRepository.getFlow(LogMajorEvents.REMINDERS).map { 11 | it.map { logEntry -> 12 | val date = Date(logEntry.time) 13 | val type = logEntry.type 14 | val message = logEntry.message 15 | 16 | "$date $type $message" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/logs/AppLogsViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.logs 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.logs.AppLogsRepository 6 | 7 | class AppLogsViewModelFactory(private val appLogsRepository: AppLogsRepository) : ViewModelProvider.Factory { 8 | override fun create(modelClass: Class): T { 9 | @Suppress("UNCHECKED_CAST") 10 | return AppLogsViewModel(appLogsRepository) as T 11 | } 12 | 13 | companion object { 14 | fun getInstance(appLogsRepository: AppLogsRepository): ViewModelProvider.Factory { 15 | return AppLogsViewModelFactory(appLogsRepository) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/main/Fab.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.main 2 | 3 | import androidx.fragment.app.FragmentActivity 4 | import com.google.android.material.floatingactionbutton.FloatingActionButton 5 | import com.orgzly.R 6 | 7 | object Fab { 8 | private fun fab(activity: FragmentActivity): FloatingActionButton? { 9 | return activity.findViewById(R.id.fab) 10 | } 11 | 12 | @JvmStatic 13 | fun hide(activity: FragmentActivity) { 14 | fab(activity)?.hide() 15 | } 16 | 17 | @JvmStatic 18 | fun show(activity: FragmentActivity) { 19 | fab(activity)?.show() 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/main/MainActivityViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.main 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class MainActivityViewModelFactory(private val dataRepository: DataRepository) : ViewModelProvider.Factory { 8 | override fun create(modelClass: Class): T { 9 | @Suppress("UNCHECKED_CAST") 10 | return MainActivityViewModel(dataRepository) as T 11 | } 12 | 13 | companion object { 14 | fun getInstance(dataRepository: DataRepository): ViewModelProvider.Factory { 15 | return MainActivityViewModelFactory(dataRepository) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/main/SharedMainActivityViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.main 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import com.orgzly.android.ui.SingleLiveEvent 6 | 7 | class SharedMainActivityViewModel : ViewModel() { 8 | data class FragmentState(val tag: String) 9 | 10 | val currentFragmentState: MutableLiveData = MutableLiveData() 11 | 12 | fun setCurrentFragment(tag: String) { 13 | currentFragmentState.value = FragmentState(tag) 14 | } 15 | 16 | val drawerLockState: MutableLiveData = MutableLiveData() 17 | 18 | fun lockDrawer() { 19 | drawerLockState.value = true 20 | } 21 | 22 | fun unlockDrawer() { 23 | drawerLockState.value = false 24 | } 25 | 26 | val openDrawerRequest: SingleLiveEvent = SingleLiveEvent() 27 | fun openDrawer() { 28 | openDrawerRequest.postValue(true) 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/note/NoteViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.note 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class NoteViewModelFactory( 8 | private val dataRepository: DataRepository, 9 | private val initialData: NoteInitialData 10 | ) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return NoteViewModel(dataRepository, initialData) as T 15 | } 16 | 17 | companion object { 18 | @JvmStatic 19 | fun getInstance(dataRepository: DataRepository, initialData: NoteInitialData) 20 | : ViewModelProvider.Factory { 21 | 22 | return NoteViewModelFactory(dataRepository, initialData) 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/notes/book/BookViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.notes.book 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class BookViewModelFactory( 8 | private val dataRepository: DataRepository, 9 | val bookId: Long 10 | ) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return BookViewModel(dataRepository, bookId) as T 15 | } 16 | 17 | companion object { 18 | fun forBook(dataRepository: DataRepository, bookId: Long): ViewModelProvider.Factory { 19 | return BookViewModelFactory(dataRepository, bookId) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/notes/query/QueryViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.notes.query 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class QueryViewModelFactory(private val dataRepository: DataRepository) : ViewModelProvider.Factory { 8 | 9 | override fun create(modelClass: Class): T { 10 | @Suppress("UNCHECKED_CAST") 11 | return QueryViewModel(dataRepository) as T 12 | } 13 | 14 | companion object { 15 | fun forQuery(dataRepository: DataRepository): ViewModelProvider.Factory { 16 | return QueryViewModelFactory(dataRepository) 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/notes/query/agenda/AgendaItem.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.notes.query.agenda 2 | 3 | import com.orgzly.android.db.entity.NoteView 4 | import com.orgzly.android.ui.TimeType 5 | import org.joda.time.DateTime 6 | 7 | sealed class AgendaItem(open val id: Long) { 8 | data class Overdue(override val id: Long) : AgendaItem(id) 9 | 10 | data class Day(override val id: Long, val day: DateTime) : AgendaItem(id) 11 | 12 | data class Note( 13 | override val id: Long, 14 | val note: NoteView, 15 | val timeType: TimeType, 16 | val isWarning: Boolean = false 17 | ) : AgendaItem(id) 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/refile/RefileViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.refile 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class RefileViewModelFactory( 8 | private val dataRepository: DataRepository, 9 | private val noteIds: Set, 10 | private val count: Int) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return RefileViewModel(dataRepository, noteIds, count) as T 15 | } 16 | 17 | companion object { 18 | fun forNotes( 19 | dataRepository: DataRepository, 20 | noteIds: Set, 21 | count: Int): ViewModelProvider.Factory { 22 | 23 | return RefileViewModelFactory(dataRepository, noteIds, count) 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/repo/RepoViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.repo 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class RepoViewModelFactory( 8 | private val dataRepository: DataRepository, 9 | private val id: Long 10 | ) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return RepoViewModel(dataRepository, id) as T 15 | } 16 | 17 | companion object { 18 | fun getInstance(dataRepository: DataRepository, id: Long): ViewModelProvider.Factory { 19 | return RepoViewModelFactory(dataRepository, id) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/repo/webdav/WebdavRepoViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.repo.webdav 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class WebdavRepoViewModelFactory( 8 | private val dataRepository: DataRepository, 9 | private val id: Long 10 | ) : ViewModelProvider.Factory { 11 | 12 | override fun create(modelClass: Class): T { 13 | @Suppress("UNCHECKED_CAST") 14 | return WebdavRepoViewModel(dataRepository, id) as T 15 | } 16 | 17 | companion object { 18 | fun getInstance(dataRepository: DataRepository, id: Long): ViewModelProvider.Factory { 19 | return WebdavRepoViewModelFactory(dataRepository, id) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/repos/ReposViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.repos 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class ReposViewModelFactory(private val dataRepository: DataRepository) : ViewModelProvider.Factory { 8 | override fun create(modelClass: Class): T { 9 | @Suppress("UNCHECKED_CAST") 10 | return ReposViewModel(dataRepository) as T 11 | } 12 | 13 | companion object { 14 | fun getInstance(dataRepository: DataRepository): ViewModelProvider.Factory { 15 | return ReposViewModelFactory(dataRepository) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/savedsearches/SavedSearchesViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.savedsearches 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class SavedSearchesViewModelFactory(private val dataRepository: DataRepository) : ViewModelProvider.Factory { 8 | override fun create(modelClass: Class): T { 9 | @Suppress("UNCHECKED_CAST") 10 | return SavedSearchesViewModel(dataRepository) as T 11 | } 12 | 13 | companion object { 14 | fun getInstance(dataRepository: DataRepository): ViewModelProvider.Factory { 15 | return SavedSearchesViewModelFactory(dataRepository) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/util/SystemActions.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("SystemActions") 2 | 3 | package com.orgzly.android.ui.util 4 | 5 | import android.app.Activity 6 | import android.content.ClipData 7 | import android.content.Context 8 | import android.content.Intent 9 | 10 | fun Context.copyPlainTextToClipboard(label: CharSequence, text: CharSequence) { 11 | getClipboardManager().let { clipboardManager -> 12 | val clip = ClipData.newPlainText(label, text) 13 | clipboardManager.setPrimaryClip(clip) 14 | } 15 | } 16 | 17 | fun Activity.sharePlainText(text: CharSequence) { 18 | val sendIntent = Intent().apply { 19 | action = Intent.ACTION_SEND 20 | putExtra(Intent.EXTRA_TEXT, text) 21 | type = "text/plain" 22 | } 23 | 24 | val shareIntent = Intent.createChooser(sendIntent, null) 25 | startActivity(shareIntent) 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/richtext/ActionableRichTextView.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.richtext 2 | 3 | import com.orgzly.android.ui.views.style.CheckboxSpan 4 | import com.orgzly.android.ui.views.style.DrawerMarkerSpan 5 | 6 | /** 7 | * Actions which user can perform in view mode. 8 | */ 9 | interface ActionableRichTextView { 10 | fun toggleDrawer(markerSpan: DrawerMarkerSpan) 11 | fun toggleCheckbox(checkboxSpan: CheckboxSpan) 12 | fun followLinkToNoteWithProperty(name: String, value: String) 13 | fun followLinkToFile(path: String) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/BoldSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.graphics.Typeface 4 | import android.text.style.StyleSpan 5 | 6 | class BoldSpan : StyleSpan(Typeface.BOLD), Offsetting { 7 | override val characterOffset = 2 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/CheckboxSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.TextPaint 4 | import android.text.style.ClickableSpan 5 | import android.util.Log 6 | import android.view.View 7 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 8 | 9 | /** 10 | * @param content is `[ ]` or `[X]` 11 | * @param rawStart is a position of dash 12 | */ 13 | class CheckboxSpan(val content: CharSequence, val rawStart: Int, val rawEnd: Int) : ClickableSpan() { 14 | 15 | override fun onClick(view: View) { 16 | Log.d("CheckboxSpan", "Checkbox clicked on $view") 17 | if (view is ActionableRichTextView) { 18 | view.toggleCheckbox(this) 19 | } 20 | } 21 | 22 | override fun updateDrawState(tp: TextPaint) { 23 | } 24 | 25 | fun isChecked(): Boolean { 26 | return content[1] != ' ' 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/CodeSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.TypefaceSpan 4 | 5 | class CodeSpan : TypefaceSpan("monospace"), Offsetting { 6 | override val characterOffset = 2 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/CustomIdLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.view.View 4 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 5 | 6 | class CustomIdLinkSpan(val type: Int, val value: String, val name: String?) : LinkSpan(), Offsetting { 7 | private val propertyValue = value.substring(PREFIX.length) 8 | 9 | override val characterOffset = when (type) { 10 | TYPE_NO_BRACKETS -> 0 11 | TYPE_BRACKETS -> 4 12 | TYPE_BRACKETS_WITH_NAME -> 6 + value.length 13 | else -> 0 14 | } 15 | 16 | override fun onClick(view: View) { 17 | if (view is ActionableRichTextView) { 18 | view.followLinkToNoteWithProperty(PROPERTY, propertyValue) 19 | } 20 | } 21 | 22 | companion object { 23 | private const val PROPERTY = "CUSTOM_ID" 24 | 25 | const val PREFIX = "#" 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/DrawerMarkerSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.TextPaint 4 | import android.text.style.ClickableSpan 5 | import android.view.View 6 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 7 | 8 | sealed class DrawerMarkerSpan : ClickableSpan() { 9 | class Start : DrawerMarkerSpan() 10 | // class DrawerEndSpan : DrawerMarkerSpan() 11 | 12 | override fun onClick(view: View) { 13 | if (view is ActionableRichTextView) { 14 | view.toggleDrawer(this) 15 | } 16 | } 17 | 18 | override fun updateDrawState(tp: TextPaint) { 19 | // tp.isUnderlineText = true 20 | // tp.color = Color.GREEN 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/DrawerSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.TextPaint 4 | import android.text.style.CharacterStyle 5 | 6 | class DrawerSpan(val name: String, val content: CharSequence, var isFolded: Boolean) : 7 | CharacterStyle(), Offsetting { 8 | 9 | override val characterOffset = if (isFolded) { 10 | // :START:… 11 | -1 + 1 + content.length + 1 + 5 12 | } else { 13 | 0 14 | } 15 | 16 | override fun updateDrawState(tp: TextPaint) { 17 | // tp.isUnderlineText = true 18 | // tp.color = Color.GREEN 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/FileLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.os.Handler 4 | import android.util.Log 5 | import android.view.View 6 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 7 | 8 | class FileLinkSpan(val type: Int, val link: String, val name: String?) : LinkSpan(), Offsetting { 9 | val path = link.substring(PREFIX.length) 10 | 11 | override val characterOffset = when (type) { 12 | TYPE_NO_BRACKETS -> 0 13 | TYPE_BRACKETS -> 4 14 | TYPE_BRACKETS_WITH_NAME -> 6 + link.length 15 | else -> 0 16 | } 17 | 18 | override fun onClick(view: View) { 19 | if (view is ActionableRichTextView) { 20 | Handler().post { // Run after onClick to prevent Snackbar from closing immediately 21 | view.followLinkToFile(path) 22 | } 23 | } 24 | } 25 | 26 | companion object { 27 | const val PREFIX = "file:" 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/FileOrNotLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.os.Handler 4 | import android.util.Log 5 | import android.view.View 6 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 7 | 8 | class FileOrNotLinkSpan(val type: Int, val link: String, val name: String?) : LinkSpan(), Offsetting { 9 | private val path = link 10 | 11 | override val characterOffset = when (type) { 12 | TYPE_NO_BRACKETS -> 0 13 | TYPE_BRACKETS -> 4 14 | TYPE_BRACKETS_WITH_NAME -> 6 + link.length 15 | else -> 0 16 | } 17 | 18 | override fun onClick(view: View) { 19 | if (view is ActionableRichTextView) { 20 | Handler().post { // Run after onClick to prevent Snackbar from closing immediately 21 | view.followLinkToFile(path) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/IdLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.view.View 4 | import com.orgzly.android.ui.views.richtext.ActionableRichTextView 5 | 6 | class IdLinkSpan(val type: Int, val link: String, val name: String?) : LinkSpan(), Offsetting { 7 | private val propertyValue = link.substring(PREFIX.length) 8 | 9 | override val characterOffset = when (type) { 10 | TYPE_NO_BRACKETS -> 0 11 | TYPE_BRACKETS -> 4 12 | TYPE_BRACKETS_WITH_NAME -> 6 + link.length 13 | else -> 0 14 | } 15 | 16 | override fun onClick(view: View) { 17 | if (view is ActionableRichTextView) { 18 | view.followLinkToNoteWithProperty(PROPERTY, propertyValue) 19 | } 20 | } 21 | 22 | companion object { 23 | private const val PROPERTY = "ID" 24 | 25 | const val PREFIX = "id:" 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/ItalicSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.graphics.Typeface 4 | import android.text.style.StyleSpan 5 | 6 | class ItalicSpan : StyleSpan(Typeface.ITALIC), Offsetting { 7 | override val characterOffset = 2 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/LinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.ClickableSpan 4 | 5 | abstract class LinkSpan : ClickableSpan() { 6 | companion object { 7 | // FIXME: These are specific to org format 8 | const val TYPE_NO_BRACKETS = 1 9 | const val TYPE_BRACKETS = 2 10 | const val TYPE_BRACKETS_WITH_NAME = 3 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/Offsetting.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | interface Offsetting { 4 | /** 5 | * Difference in number of characters between source text and what's displayed. 6 | */ 7 | val characterOffset: Int 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/SearchLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.view.View 4 | 5 | class SearchLinkSpan(val type: Int, val link: String, val name: String?) : LinkSpan(), Offsetting { 6 | // private val searchString = link 7 | 8 | override val characterOffset = when (type) { 9 | TYPE_NO_BRACKETS -> 0 10 | TYPE_BRACKETS -> 4 11 | TYPE_BRACKETS_WITH_NAME -> 6 12 | else -> 0 13 | } 14 | 15 | override fun onClick(widget: View) { 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/StrikeSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.StrikethroughSpan 4 | 5 | class StrikeSpan : StrikethroughSpan(), Offsetting { 6 | override val characterOffset = 2 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/UnderlinedSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.UnderlineSpan 4 | 5 | class UnderlinedSpan : UnderlineSpan(), Offsetting { 6 | override val characterOffset = 2 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/UrlLinkSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.URLSpan 4 | import android.view.View 5 | 6 | class UrlLinkSpan(val type: Int, val url: String, val name: String?) : LinkSpan(), Offsetting { 7 | override val characterOffset = when (type) { 8 | TYPE_NO_BRACKETS -> 0 9 | TYPE_BRACKETS -> 4 10 | TYPE_BRACKETS_WITH_NAME -> 6 + url.length 11 | else -> 0 12 | } 13 | 14 | override fun onClick(widget: View) { 15 | URLSpan(url).onClick(widget) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/ui/views/style/VerbatimSpan.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.ui.views.style 2 | 3 | import android.text.style.TypefaceSpan 4 | 5 | class VerbatimSpan : TypefaceSpan("monospace"), Offsetting { 6 | override val characterOffset = 2 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookCreate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class BookCreate(val name: String) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.createBook(name) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookCycleVisibility.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.db.entity.Book 5 | 6 | class BookCycleVisibility(val book: Book) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.cycleVisibility(book.id) 9 | 10 | return UseCaseResult() 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookDelete.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class BookDelete(val bookId: Long, val deleteLinked: Boolean) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | val book = dataRepository.getBookView(bookId) ?: throw NotFound() 8 | 9 | dataRepository.deleteBook(book, deleteLinked) 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_DATA_MODIFIED 14 | ) 15 | } 16 | 17 | class NotFound: Throwable() 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookExport.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.BookFormat 4 | import com.orgzly.android.data.DataRepository 5 | 6 | /** 7 | * Exports book. Link is not updated, book stays linked to the same remote book. 8 | */ 9 | class BookExport(val bookId: Long, val format: BookFormat) : UseCase() { 10 | override fun run(dataRepository: DataRepository): UseCaseResult { 11 | val file = dataRepository.exportBook(bookId, BookFormat.ORG) 12 | 13 | return UseCaseResult(userData = file) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookExportToUri.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.BookFormat 4 | import com.orgzly.android.data.DataRepository 5 | import java.io.OutputStream 6 | import java.io.OutputStreamWriter 7 | 8 | /** 9 | * Exports book. Link is not updated, book stays linked to the same remote book. 10 | */ 11 | class BookExportToUri(val bookId: Long, val stream: OutputStream, val format: BookFormat) : UseCase() { 12 | override fun run(dataRepository: DataRepository): UseCaseResult { 13 | val book = dataRepository.getBookOrThrow(bookId) 14 | 15 | OutputStreamWriter(stream).use { writer -> 16 | dataRepository.exportBook(book, writer) 17 | } 18 | 19 | return UseCaseResult() 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookForceLoad.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | /** 6 | * Load book from repository. 7 | */ 8 | class BookForceLoad(val bookId: Long) : UseCase() { 9 | override fun run(dataRepository: DataRepository): UseCaseResult { 10 | dataRepository.forceLoadBook(bookId) 11 | 12 | return UseCaseResult( 13 | modifiesLocalData = true 14 | ) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookForceSave.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | /** 6 | * Saves book to its linked remote book, or to the one-and-only repository. 7 | */ 8 | class BookForceSave(val bookId: Long) : UseCase() { 9 | override fun run(dataRepository: DataRepository): UseCaseResult { 10 | dataRepository.forceSaveBook(bookId) 11 | 12 | return UseCaseResult() 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookImportFromUri.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.net.Uri 4 | import com.orgzly.android.BookFormat 5 | import com.orgzly.android.data.DataRepository 6 | 7 | /** 8 | * Load notebook from URI saving it using specified name. 9 | */ 10 | class BookImportFromUri(val bookName: String, val format: BookFormat, val uri: Uri) : UseCase() { 11 | override fun run(dataRepository: DataRepository): UseCaseResult { 12 | // TODO: Go through ActionService? 13 | dataRepository.importBook(bookName, format, uri) 14 | 15 | return UseCaseResult( 16 | modifiesLocalData = true, 17 | triggersSync = SYNC_DATA_MODIFIED 18 | ) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookImportGettingStarted.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.content.Intent 4 | import com.orgzly.android.AppIntent 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class BookImportGettingStarted : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | dataRepository.importGettingStartedBook() 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_DATA_MODIFIED 14 | ) 15 | } 16 | 17 | override fun toAction(): String { 18 | return AppIntent.ACTION_IMPORT_GETTING_STARTED_NOTEBOOK 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookLinkUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.db.entity.Repo 5 | 6 | class BookLinkUpdate @JvmOverloads constructor(val bookId: Long, val link: Repo? = null) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.setLink(bookId, link) 9 | 10 | return UseCaseResult() 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookRename.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.db.entity.BookView 5 | 6 | class BookRename(val bookView: BookView, val name: String) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.renameBook(bookView, name) 9 | 10 | return UseCaseResult( 11 | modifiesLocalData = true, 12 | triggersSync = SYNC_DATA_MODIFIED 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookScrollToNote.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class BookScrollToNote(val noteId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.openBookForNote(noteId, false) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookSparseTreeForNote.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class BookSparseTreeForNote(val noteId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.openBookForNote(noteId, true) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/BookUpdatePreface.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | /** 6 | * Both from editing preface and saving the changes and from toggling checkboxes etc. 7 | */ 8 | class BookUpdatePreface(val bookId: Long, val preface: String) : UseCase() { 9 | override fun run(dataRepository: DataRepository): UseCaseResult { 10 | dataRepository.setBookPreface(bookId, preface) 11 | 12 | return UseCaseResult( 13 | modifiesLocalData = true, 14 | triggersSync = SYNC_DATA_MODIFIED 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/DatabaseClear.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class DatabaseClear : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.clearDatabase() 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true 11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteCopy.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.db.NotesClipboard 4 | import com.orgzly.android.data.DataRepository 5 | 6 | class NoteCopy(val bookId: Long, val ids: Set) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val clipboard = NotesClipboard.create(dataRepository, ids).apply { 9 | save() 10 | } 11 | 12 | return UseCaseResult( 13 | userData = clipboard 14 | ) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteCreate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.ui.NotePlace 5 | import com.orgzly.android.ui.note.NotePayload 6 | 7 | class NoteCreate(val notePayload: NotePayload, val notePlace: NotePlace) : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | val note = dataRepository.createNote(notePayload, notePlace) 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_NOTE_CREATED, 14 | userData = note) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteCreateFromNotification.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteCreateFromNotification(val title: String) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.createNoteFromNotification(title) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_NOTE_CREATED 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteCut.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.db.NotesClipboard 4 | import com.orgzly.android.data.DataRepository 5 | 6 | class NoteCut(val bookId: Long, val ids: Set) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val clipboard = NotesClipboard.create(dataRepository, ids).apply { 9 | save() 10 | } 11 | 12 | dataRepository.deleteNotes(bookId, ids) 13 | 14 | return UseCaseResult( 15 | modifiesLocalData = true, 16 | triggersSync = SYNC_DATA_MODIFIED, 17 | userData = clipboard 18 | ) 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteDelete.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteDelete(val bookId: Long, val ids: Set) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | val count = dataRepository.deleteNotes(bookId, ids) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED, 12 | userData = count 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteDemote.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteDemote(val noteIds: Set) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | val count = dataRepository.demoteNotes(noteIds) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED, 12 | userData = count 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteFindWithProperty.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteFindWithProperty(val name: String, val value: String) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | val note = dataRepository.findNoteHavingProperty(name, value) 8 | 9 | return UseCaseResult( 10 | userData = note 11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteMove.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteMove(val bookId: Long, val noteIds: Set, val offset: Int) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.moveNote(bookId, noteIds, offset) 8 | 9 | // FIXME: Auto-sync is handled on action bar destroy instead 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_DATA_MODIFIED 14 | ) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NotePaste.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.db.NotesClipboard 4 | import com.orgzly.android.data.DataRepository 5 | import com.orgzly.android.ui.Place 6 | 7 | class NotePaste(val bookId: Long, val noteId: Long, val place: Place) : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | val clipboard = NotesClipboard.load() 10 | 11 | val count = dataRepository.pasteNotes(clipboard, bookId, noteId, place) 12 | 13 | return UseCaseResult( 14 | modifiesLocalData = count > 0, 15 | triggersSync = if (count > 0) SYNC_DATA_MODIFIED else SYNC_NOT_REQUIRED, 16 | userData = count) 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NotePromote.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NotePromote(val noteIds: Set) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | val count = dataRepository.promoteNotes(noteIds) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED, 12 | userData = count 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteReparseStateAndTitles.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.content.Intent 4 | import com.orgzly.android.AppIntent 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class NoteReparseStateAndTitles : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | dataRepository.reParseNotesStateAndTitles() 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_DATA_MODIFIED 14 | ) 15 | } 16 | 17 | override fun toAction(): String { 18 | return AppIntent.ACTION_REPARSE_NOTES 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteSyncCreatedAtTimeWithProperty.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.content.Intent 4 | import com.orgzly.android.AppIntent 5 | import com.orgzly.android.data.DataRepository 6 | 7 | class NoteSyncCreatedAtTimeWithProperty : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | dataRepository.syncCreatedAtTimeWithProperty() 10 | 11 | return UseCaseResult( 12 | modifiesLocalData = true, 13 | triggersSync = SYNC_DATA_MODIFIED 14 | ) 15 | } 16 | 17 | override fun toAction(): String { 18 | return AppIntent.ACTION_SYNC_CREATED_AT_WITH_PROPERTY 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteToggleFolding.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteToggleFolding(val noteId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.toggleNoteFoldedState(noteId) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteToggleFoldingSubtree.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteToggleFoldingSubtree(val noteId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.toggleNoteFoldedStateForSubtree(noteId) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.ui.note.NotePayload 5 | import java.lang.IllegalStateException 6 | 7 | class NoteUpdate(val noteId: Long, val notePayload: NotePayload) : UseCase() { 8 | override fun run(dataRepository: DataRepository): UseCaseResult { 9 | val note = dataRepository.updateNote(noteId, notePayload) 10 | ?: throw IllegalStateException("Note not found") 11 | 12 | return UseCaseResult( 13 | modifiesLocalData = true, 14 | triggersSync = SYNC_DATA_MODIFIED, 15 | userData = note) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateClockingState.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteUpdateClockingState(val noteIds: Set, val type: Int) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.setNotesClockingState(noteIds, type) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateContent.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | /** 6 | * From toggling checkboxes, folding drawers, etc. 7 | */ 8 | class NoteUpdateContent(val bookId: Long, val noteId: Long, val content: String?) : UseCase() { 9 | override fun run(dataRepository: DataRepository): UseCaseResult { 10 | dataRepository.updateNoteContent(bookId, noteId, content) 11 | 12 | return UseCaseResult( 13 | modifiesLocalData = true, 14 | triggersSync = SYNC_DATA_MODIFIED 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateDeadlineTime.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.org.datetime.OrgDateTime 5 | 6 | class NoteUpdateDeadlineTime(val noteIds: Set, val time: OrgDateTime?) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.setNotesDeadlineTime(noteIds, time) 9 | 10 | return UseCaseResult( 11 | modifiesLocalData = true, 12 | triggersSync = SYNC_DATA_MODIFIED 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateScheduledTime.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.org.datetime.OrgDateTime 5 | 6 | class NoteUpdateScheduledTime(val noteIds: Set, val time: OrgDateTime?) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.setNotesScheduledTime(noteIds, time) 9 | 10 | return UseCaseResult( 11 | modifiesLocalData = true, 12 | triggersSync = SYNC_DATA_MODIFIED 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateState.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteUpdateState(val noteIds: Set, val state: String?) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.setNotesState(noteIds, state) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateStateDone.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class NoteUpdateStateDone(val noteId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.setNoteStateToDone(noteId) 8 | 9 | return UseCaseResult( 10 | modifiesLocalData = true, 11 | triggersSync = SYNC_DATA_MODIFIED 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/NoteUpdateStateToggle.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | /** 6 | * Sets the state of notes to the first done-type state defined in Settings. 7 | */ 8 | class NoteUpdateStateToggle(val noteIds: Set) : UseCase() { 9 | override fun run(dataRepository: DataRepository): UseCaseResult { 10 | dataRepository.toggleNotesState(noteIds) 11 | 12 | return UseCaseResult( 13 | modifiesLocalData = true, 14 | triggersSync = SYNC_DATA_MODIFIED 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/RepoCreate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.repos.RepoWithProps 5 | 6 | class RepoCreate(val props: RepoWithProps) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val id = dataRepository.createRepo(props) 9 | 10 | return UseCaseResult(id) 11 | } 12 | 13 | class AlreadyExists: Throwable() 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/RepoDelete.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class RepoDelete(val repoId: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.deleteRepo(repoId) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/RepoUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.repos.RepoWithProps 5 | 6 | class RepoUpdate(val repoWithProps: RepoWithProps) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val id = dataRepository.updateRepo(repoWithProps) 9 | 10 | return UseCaseResult(id) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchCreate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.db.entity.SavedSearch 5 | 6 | class SavedSearchCreate(val savedSearch: SavedSearch) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.createSavedSearch(savedSearch) 9 | 10 | return UseCaseResult( 11 | modifiesListWidget = true 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchDelete.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class SavedSearchDelete(val ids: Set) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.deleteSavedSearches(ids) 8 | 9 | return UseCaseResult( 10 | modifiesListWidget = true 11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchExport.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.net.Uri 4 | import com.orgzly.android.data.DataRepository 5 | 6 | class SavedSearchExport(val uri: Uri? = null) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val count = dataRepository.exportSavedSearches(uri) 9 | 10 | return UseCaseResult(userData = count) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchImport.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.net.Uri 4 | import com.orgzly.android.data.DataRepository 5 | 6 | class SavedSearchImport(val uri: Uri) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | val count = dataRepository.importSavedSearches(uri) 9 | 10 | return UseCaseResult( 11 | userData = count, 12 | modifiesListWidget = true 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchMoveDown.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class SavedSearchMoveDown(val id: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.moveSavedSearchDown(id) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchMoveUp.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | 5 | class SavedSearchMoveUp(val id: Long) : UseCase() { 6 | override fun run(dataRepository: DataRepository): UseCaseResult { 7 | dataRepository.moveSavedSearchUp(id) 8 | 9 | return UseCaseResult() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/SavedSearchUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.data.DataRepository 4 | import com.orgzly.android.db.entity.SavedSearch 5 | 6 | class SavedSearchUpdate(val savedSearch: SavedSearch) : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.updateSavedSearch(savedSearch) 9 | 10 | return UseCaseResult( 11 | modifiesListWidget = true 12 | ) 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/TimestampUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import com.orgzly.android.AppIntent 4 | import com.orgzly.android.data.DataRepository 5 | 6 | class TimestampUpdate : UseCase() { 7 | override fun run(dataRepository: DataRepository): UseCaseResult { 8 | dataRepository.updateTimestamps() 9 | 10 | return UseCaseResult( 11 | modifiesLocalData = true 12 | ) 13 | } 14 | 15 | override fun toAction(): String { 16 | return AppIntent.ACTION_UPDATE_TIMESTAMPS 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/UseCase.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | import android.content.Intent 4 | import com.orgzly.android.data.DataRepository 5 | 6 | abstract class UseCase { 7 | abstract fun run(dataRepository: DataRepository): UseCaseResult 8 | 9 | open fun toAction(): String { 10 | throw NotImplementedError("No action") 11 | } 12 | 13 | companion object { 14 | val TAG: String = UseCase::class.java.name 15 | 16 | const val SYNC_NOT_REQUIRED = 0 17 | const val SYNC_DATA_MODIFIED = 1 18 | const val SYNC_NOTE_CREATED = 2 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/usecase/UseCaseResult.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.usecase 2 | 3 | data class UseCaseResult constructor( 4 | val modifiesLocalData: Boolean = false, 5 | val modifiesListWidget: Boolean = false, 6 | val triggersSync: Int = UseCase.SYNC_NOT_REQUIRED, 7 | val userData: Any? = null) { 8 | constructor(userData: Any?) : this(false, false, UseCase.SYNC_NOT_REQUIRED, userData) 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/orgzly/android/util/BroadcastReceiverExt.kt: -------------------------------------------------------------------------------- 1 | package com.orgzly.android.util 2 | 3 | import android.content.BroadcastReceiver 4 | import kotlinx.coroutines.CoroutineScope 5 | import kotlinx.coroutines.GlobalScope 6 | import kotlinx.coroutines.launch 7 | 8 | fun BroadcastReceiver.async( 9 | coroutineScope: CoroutineScope = GlobalScope, 10 | block: suspend () -> Unit 11 | ) { 12 | val result = goAsync() 13 | coroutineScope.launch { 14 | try { 15 | block() 16 | } finally { 17 | // Always call finish(), even if the coroutineScope was cancelled 18 | result.finish() 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fragment_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fragment_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/rotate_counterclockwise.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_from_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_from_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_to_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/cic_new_above.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/cic_new_below.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/cic_new_under.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_abc.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_access_time.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_add.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_alarm.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_arrow_back.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_arrow_downward.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_arrow_drop_down.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_arrow_forward.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_arrow_upward.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_center_focus_strong.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_check_circle_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_close.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_cloud_download_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_cloud_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_cloud_upload_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_content_copy.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_content_cut.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_content_paste.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_create_new_folder.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_done.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_edit.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_flag.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_folder_open.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_format_list_bulleted.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_help_outline.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_hourglass_bottom.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_hourglass_disabled.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_hourglass_empty.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_hourglass_top.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_info_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_insert_drive_file.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_keyboard_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_keyboard_arrow_up.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_label_outline.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_library_books.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_link.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_more_horiz.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_move_to_inbox.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_north.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_notes.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_notifications_none.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_open_in_new.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_palette.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_remove_red_eye.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_search.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_share.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_snooze.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_south.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_south_east.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_star_border.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_storage.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_swap_vert.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_swipe_left.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_swipe_right.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_sync.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_sync_problem.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_today.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_unfold_more.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_warning.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_widgets.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bullet.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bullet_folded.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cic_shortcut_new_note_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cic_shortcut_notebook_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cic_shortcut_sync_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_scroll_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_scroll_line_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_scroll_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_scroll_thumb_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_widget_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orgzly/orgzly-android/0783e64e122ec4a9595c98c99b975f3e7bbf2870/app/src/main/res/drawable/list_widget_preview.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_bookchooser.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_list_widget_selection.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_share.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_certificates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_progress_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_simple_one_liner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_spinner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_timestamp_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_item_sync_failed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_item_sync_needed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dropdown_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/indent.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_list_widget_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_preface.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_repo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_saved_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 21 | 22 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_popup_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |