diff --git a/src/Notes/.gradle/8.0/executionHistory/executionHistory.bin b/src/Notes/.gradle/8.0/executionHistory/executionHistory.bin new file mode 100644 index 0000000..bb0f83e Binary files /dev/null and b/src/Notes/.gradle/8.0/executionHistory/executionHistory.bin differ diff --git a/src/Notes/.gradle/8.0/executionHistory/executionHistory.lock b/src/Notes/.gradle/8.0/executionHistory/executionHistory.lock new file mode 100644 index 0000000..a8a4684 Binary files /dev/null and b/src/Notes/.gradle/8.0/executionHistory/executionHistory.lock differ diff --git a/src/Notes/.gradle/8.0/fileHashes/fileHashes.bin b/src/Notes/.gradle/8.0/fileHashes/fileHashes.bin new file mode 100644 index 0000000..9f47349 Binary files /dev/null and b/src/Notes/.gradle/8.0/fileHashes/fileHashes.bin differ diff --git a/src/Notes/.gradle/8.0/fileHashes/fileHashes.lock b/src/Notes/.gradle/8.0/fileHashes/fileHashes.lock new file mode 100644 index 0000000..2a4f76c Binary files /dev/null and b/src/Notes/.gradle/8.0/fileHashes/fileHashes.lock differ diff --git a/src/Notes/.gradle/8.0/fileHashes/resourceHashesCache.bin b/src/Notes/.gradle/8.0/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..285bc0c Binary files /dev/null and b/src/Notes/.gradle/8.0/fileHashes/resourceHashesCache.bin differ diff --git a/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..da7f435 Binary files /dev/null and b/src/Notes/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin b/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..45267e7 Binary files /dev/null and b/src/Notes/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/src/Notes/.gradle/file-system.probe b/src/Notes/.gradle/file-system.probe new file mode 100644 index 0000000..b6d9802 Binary files /dev/null and b/src/Notes/.gradle/file-system.probe differ diff --git a/src/Notes/app/build/intermediates/apk/debug/app-debug.apk b/src/Notes/app/build/intermediates/apk/debug/app-debug.apk new file mode 100644 index 0000000..82435ad Binary files /dev/null and b/src/Notes/app/build/intermediates/apk/debug/app-debug.apk differ diff --git a/src/Notes/app/build/intermediates/apk_ide_redirect_file/debug/redirect.txt b/src/Notes/app/build/intermediates/apk_ide_redirect_file/debug/redirect.txt new file mode 100644 index 0000000..46dacc6 --- /dev/null +++ b/src/Notes/app/build/intermediates/apk_ide_redirect_file/debug/redirect.txt @@ -0,0 +1,2 @@ +#- File Locator - +listingFile=../../apk/debug/output-metadata.json diff --git a/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_0/graph.bin b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_0/graph.bin new file mode 100644 index 0000000..8737910 Binary files /dev/null and b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_0/graph.bin differ diff --git a/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_3/graph.bin b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_3/graph.bin new file mode 100644 index 0000000..8fb5bea Binary files /dev/null and b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_3/graph.bin differ diff --git a/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_5/graph.bin b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_5/graph.bin new file mode 100644 index 0000000..a94134c Binary files /dev/null and b/src/Notes/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_5/graph.bin differ diff --git a/src/Notes/app/build/intermediates/dex/debug/mergeDexDebug/classes.dex b/src/Notes/app/build/intermediates/dex/debug/mergeDexDebug/classes.dex new file mode 100644 index 0000000..1fe2149 Binary files /dev/null and b/src/Notes/app/build/intermediates/dex/debug/mergeDexDebug/classes.dex differ diff --git a/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/compile-file-map.properties b/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/compile-file-map.properties new file mode 100644 index 0000000..2215ade --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/compile-file-map.properties @@ -0,0 +1,96 @@ +#Fri Dec 22 19:43:31 CST 2023 +net.micode.notes.app-main-6\:/color/primary_text_dark.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\color_primary_text_dark.xml.flat +net.micode.notes.app-main-6\:/color/secondary_text_dark.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\color_secondary_text_dark.xml.flat +net.micode.notes.app-main-6\:/drawable-hdpi/bg_btn_set_color.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_bg_btn_set_color.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/bg_color_btn_mask.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_bg_color_btn_mask.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/call_record.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_call_record.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/clock.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_clock.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/delete.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_delete.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/dropdown_icon.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_dropdown_icon.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_blue.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_blue.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_green.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_green.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_red.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_red.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_title_blue.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_title_blue.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_title_green.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_title_green.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_title_red.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_title_red.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_title_white.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_title_white.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_title_yellow.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_title_yellow.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_white.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_white.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/edit_yellow.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_edit_yellow.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/font_large.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_font_large.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/font_normal.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_font_normal.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/font_size_selector_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_font_size_selector_bg.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/font_small.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_font_small.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/font_super.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_font_super.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/icon_app.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_icon_app.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_background.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_background.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_blue_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_blue_down.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_blue_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_blue_middle.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_blue_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_blue_single.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_blue_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_blue_up.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_folder.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_folder.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_footer_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_footer_bg.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_green_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_green_down.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_green_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_green_middle.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_green_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_green_single.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_green_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_green_up.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_red_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_red_down.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_red_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_red_middle.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_red_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_red_single.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_red_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_red_up.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_white_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_white_down.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_white_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_white_middle.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_white_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_white_single.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_white_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_white_up.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_yellow_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_yellow_down.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_yellow_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_yellow_middle.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_yellow_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_yellow_single.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/list_yellow_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_list_yellow_up.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/menu_delete.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_menu_delete.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/menu_move.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_menu_move.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/new_note_normal.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_new_note_normal.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/new_note_pressed.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_new_note_pressed.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/note_edit_color_selector_panel.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_note_edit_color_selector_panel.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/notification.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_notification.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/search_result.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_search_result.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/selected.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_selected.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/title_alert.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_title_alert.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/title_bar_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_title_bar_bg.9.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_2x_blue.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_2x_blue.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_2x_green.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_2x_green.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_2x_red.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_2x_red.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_2x_white.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_2x_white.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_2x_yellow.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_2x_yellow.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_4x_blue.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_4x_blue.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_4x_green.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_4x_green.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_4x_red.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_4x_red.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_4x_white.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_4x_white.png.flat +net.micode.notes.app-main-6\:/drawable-hdpi/widget_4x_yellow.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable-hdpi_widget_4x_yellow.png.flat +net.micode.notes.app-main-6\:/drawable/new_note.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\drawable_new_note.xml.flat +net.micode.notes.app-main-6\:/layout/account_dialog_title.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_account_dialog_title.xml.flat +net.micode.notes.app-main-6\:/layout/add_account_text.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_add_account_text.xml.flat +net.micode.notes.app-main-6\:/layout/datetime_picker.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_datetime_picker.xml.flat +net.micode.notes.app-main-6\:/layout/dialog_edit_text.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_dialog_edit_text.xml.flat +net.micode.notes.app-main-6\:/layout/folder_list_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_folder_list_item.xml.flat +net.micode.notes.app-main-6\:/layout/note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_edit.xml.flat +net.micode.notes.app-main-6\:/layout/note_edit_list_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_edit_list_item.xml.flat +net.micode.notes.app-main-6\:/layout/note_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_item.xml.flat +net.micode.notes.app-main-6\:/layout/note_list.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_list.xml.flat +net.micode.notes.app-main-6\:/layout/note_list_dropdown_menu.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_list_dropdown_menu.xml.flat +net.micode.notes.app-main-6\:/layout/note_list_footer.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_note_list_footer.xml.flat +net.micode.notes.app-main-6\:/layout/settings_header.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_settings_header.xml.flat +net.micode.notes.app-main-6\:/layout/widget_2x.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_widget_2x.xml.flat +net.micode.notes.app-main-6\:/layout/widget_4x.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\layout_widget_4x.xml.flat +net.micode.notes.app-main-6\:/menu/call_note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_call_note_edit.xml.flat +net.micode.notes.app-main-6\:/menu/call_record_folder.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_call_record_folder.xml.flat +net.micode.notes.app-main-6\:/menu/note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_note_edit.xml.flat +net.micode.notes.app-main-6\:/menu/note_list.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_note_list.xml.flat +net.micode.notes.app-main-6\:/menu/note_list_dropdown.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_note_list_dropdown.xml.flat +net.micode.notes.app-main-6\:/menu/note_list_options.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_note_list_options.xml.flat +net.micode.notes.app-main-6\:/menu/sub_folder.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\menu_sub_folder.xml.flat +net.micode.notes.app-main-6\:/raw-zh-rCN/introduction=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\raw-zh-rCN_introduction.flat +net.micode.notes.app-main-6\:/raw/introduction=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\raw_introduction.flat +net.micode.notes.app-main-6\:/xml/preferences.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\xml_preferences.xml.flat +net.micode.notes.app-main-6\:/xml/searchable.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\xml_searchable.xml.flat +net.micode.notes.app-main-6\:/xml/widget_2x_info.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\xml_widget_2x_info.xml.flat +net.micode.notes.app-main-6\:/xml/widget_4x_info.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\merged_res\\debug\\xml_widget_4x_info.xml.flat diff --git a/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/merger.xml b/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/merger.xml new file mode 100644 index 0000000..5a13304 --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/debug/mergeDebugResources/merger.xml @@ -0,0 +1,56 @@ + + + -%s + --%s + --%s + --%s + + Messaging + Email + #335b5b5b33sp26sp20sp17sp14spNotesNotes 2x2Notes 4x4No associated note found, click to create associated note.Privacy mode,can not see note content...Add noteDelete reminder successfullySet reminderExpiredyyyyMMddMMMd kk:mmGot itTake a lookCallSend emailBrowse webOpen map/MIUI/notes/notes_%s.txt(%d)New FolderExport textSyncCancel syncingSettingsSearchDeleteMove to folder%d selectedNothing selected, the operation is invalidSelect allDeselect allFont sizeSmallMediumLargeSuperEnter check listLeave check listView folderDelete folderChange folder nameThe folder %1$s exist, please renameShareSend to homeRemind meDelete reminderSelect folderParent folderNote added to homeConfirm to delete folder and its notes?Delete selected notesConfirm to delete the selected %d notes?Confirm to delete this note?Have moved selected %1$d notes to %2$s folderSD card busy, not available nowExport failed, please check SD cardThe note is not existSorry, can not set clock on empty noteSorry, can not send and empty note to homeExport successfulExport failExport text file (%1$s) to SD (%2$s) directorySyncing notes...Sync is successfulSync is failedSync is canceledSync is successful with account %1$sSync failed, please check network and account settingsSync failed, internal error occursSync is canceledLogging into %1$s...Getting remote note list...Synchronize local notes with Google Task...SettingsSync accountSync notes with google taskLast sync time %1$syyyy-MM-dd hh:mm:ssAdd accountChange sync accountRemove sync accountCancelSync immediatelyCancel syncingCurrent account %1$sAll sync related information will be deleted, which may result in duplicated items sometimeSync notesPlease select a google account. Local notes will be synced with google task.Cannot change the account because sync is in progress%1$s has been set as the sync accountNew note background color randomDeleteCall notesInput nameSearching NotesSearch notesText in your notesNotessetcancel + %1$s result for \"%2$s\" + + %1$s results for \"%2$s\" + + 短信 + 邮件 + 便签便签2x2便签4x4没有关联内容,点击新建便签。访客模式下,便签内容不可见...新建便签成功删除提醒创建提醒已过期yyyyMMddMM月dd日 kk:mm知道了查看呼叫电话发送邮件浏览网页打开地图新建文件夹导出文本同步取消同步设置搜索删除移动到文件夹选中了 %d 项没有选中项,操作无效全选取消全选文字大小正常超大进入清单模式退出清单模式查看文件夹刪除文件夹修改文件夹名称文件夹 %1$s 已存在,请重新命名分享发送到桌面提醒我删除提醒选择文件夹上一级文件夹已添加到桌面删除确认要删除所选的 %d 条便签吗?确认要删除该条便签吗?确认删除文件夹及所包含的便签吗?已将所选 %1$d 条便签移到 %2$s 文件夹SD卡被占用,不能操作导出文本时发生错误,请检查SD卡要查看的便签不存在不能为空便签设置闹钟提醒不能将空便签发送到桌面导出成功导出失败已将文本文件(%1$s)输出至SD卡(%2$s)目录同步便签...同步成功同步失败同步已取消与%1$s同步成功同步失败,请检查网络和帐号设置同步失败,发生内部错误同步已取消登录%1$s...正在获取服务器便签列表...正在同步本地便签...设置同步账号与google task同步便签记录上次同步于 %1$s添加账号更换账号删除账号取消立即同步取消同步当前帐号 %1$s如更换同步帐号,过去的帐号同步信息将被清空,再次切换的同时可能会造成数据重复同步便签请选择google帐号,便签将与该帐号的google task内容同步。正在同步中,不能修改同步帐号同步帐号已设置为%1$s新建便签背景颜色随机删除通话便签请输入名称正在搜索便签搜索便签便签中的文字便签设置取消 + %1$s 条符合“%2$s”的搜索结果 + + 短信 + 郵件 + 便簽便簽2x2便簽4x4沒有關聯內容,點擊新建便簽。訪客模式下,便籤內容不可見...新建便簽成功刪除提醒創建提醒已過期yyyyMMddMM月dd日 kk:mm知道了查看呼叫電話發送郵件浏覽網頁打開地圖已將所選 %1$d 便籤移到 %2$s 文件夾新建文件夾導出文本同步取消同步設置搜尋刪除移動到文件夾選中了 %d 項沒有選中項,操作無效全選取消全選文字大小正常超大進入清單模式退出清單模式查看文件夾刪除文件夾修改文件夾名稱文件夾 %1$s 已存在,請重新命名分享發送到桌面提醒我刪除提醒選擇文件夾上一級文件夾已添加到桌面刪除确认要刪除所選的 %d 條便籤嗎?确认要删除該條便籤嗎?確認刪除檔夾及所包含的便簽嗎?SD卡被佔用,不能操作導出TXT時發生錯誤,請檢查SD卡要查看的便籤不存在不能爲空便籤設置鬧鐘提醒不能將空便籤發送到桌面導出成功導出失敗已將文本文件(%1$s)導出至SD(%2$s)目錄同步便簽...同步成功同步失敗同步已取消與%1$s同步成功同步失敗,請檢查網絡和帳號設置同步失敗,發生內部錯誤同步已取消登陸%1$s...正在獲取服務器便籤列表...正在同步本地便籤...設置同步賬號与google task同步便簽記錄上次同步于 %1$s添加賬號更換賬號刪除賬號取消立即同步取消同步當前帳號 %1$s如更換同步帳號,過去的帳號同步信息將被清空,再次切換的同時可能會造成數據重復同步便簽請選擇google帳號,便簽將與該帳號的google task內容同步。正在同步中,不能修改同步帳號同步帳號已設置為%1$s新建便籤背景顏色隨機刪除通話便籤請輸入名稱正在搜索便籤搜索便籤便籤中的文字便籤設置取消 + %1$s 條符合”%2$s“的搜尋結果 + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties new file mode 100644 index 0000000..edd62ef --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties @@ -0,0 +1,96 @@ +#Fri Dec 22 19:43:31 CST 2023 +net.micode.notes.app-main-5\:/color/primary_text_dark.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\color\\primary_text_dark.xml +net.micode.notes.app-main-5\:/color/secondary_text_dark.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\color\\secondary_text_dark.xml +net.micode.notes.app-main-5\:/drawable-hdpi/bg_btn_set_color.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\bg_btn_set_color.png +net.micode.notes.app-main-5\:/drawable-hdpi/bg_color_btn_mask.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\bg_color_btn_mask.png +net.micode.notes.app-main-5\:/drawable-hdpi/call_record.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\call_record.png +net.micode.notes.app-main-5\:/drawable-hdpi/clock.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\clock.png +net.micode.notes.app-main-5\:/drawable-hdpi/delete.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\delete.png +net.micode.notes.app-main-5\:/drawable-hdpi/dropdown_icon.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\dropdown_icon.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_blue.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_blue.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_green.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_green.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_red.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_red.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_title_blue.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_title_blue.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_title_green.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_title_green.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_title_red.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_title_red.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_title_white.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_title_white.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_title_yellow.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_title_yellow.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_white.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_white.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/edit_yellow.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\edit_yellow.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/font_large.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\font_large.png +net.micode.notes.app-main-5\:/drawable-hdpi/font_normal.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\font_normal.png +net.micode.notes.app-main-5\:/drawable-hdpi/font_size_selector_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\font_size_selector_bg.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/font_small.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\font_small.png +net.micode.notes.app-main-5\:/drawable-hdpi/font_super.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\font_super.png +net.micode.notes.app-main-5\:/drawable-hdpi/icon_app.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\icon_app.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_background.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_background.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_blue_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_blue_down.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_blue_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_blue_middle.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_blue_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_blue_single.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_blue_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_blue_up.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_folder.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_folder.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_footer_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_footer_bg.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_green_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_green_down.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_green_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_green_middle.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_green_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_green_single.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_green_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_green_up.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_red_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_red_down.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_red_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_red_middle.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_red_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_red_single.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_red_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_red_up.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_white_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_white_down.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_white_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_white_middle.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_white_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_white_single.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_white_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_white_up.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_yellow_down.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_yellow_down.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_yellow_middle.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_yellow_middle.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_yellow_single.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_yellow_single.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/list_yellow_up.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\list_yellow_up.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/menu_delete.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\menu_delete.png +net.micode.notes.app-main-5\:/drawable-hdpi/menu_move.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\menu_move.png +net.micode.notes.app-main-5\:/drawable-hdpi/new_note_normal.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\new_note_normal.png +net.micode.notes.app-main-5\:/drawable-hdpi/new_note_pressed.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\new_note_pressed.png +net.micode.notes.app-main-5\:/drawable-hdpi/note_edit_color_selector_panel.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\note_edit_color_selector_panel.png +net.micode.notes.app-main-5\:/drawable-hdpi/notification.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\notification.png +net.micode.notes.app-main-5\:/drawable-hdpi/search_result.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\search_result.png +net.micode.notes.app-main-5\:/drawable-hdpi/selected.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\selected.png +net.micode.notes.app-main-5\:/drawable-hdpi/title_alert.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\title_alert.png +net.micode.notes.app-main-5\:/drawable-hdpi/title_bar_bg.9.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\title_bar_bg.9.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_2x_blue.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_2x_blue.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_2x_green.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_2x_green.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_2x_red.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_2x_red.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_2x_white.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_2x_white.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_2x_yellow.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_2x_yellow.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_4x_blue.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_4x_blue.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_4x_green.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_4x_green.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_4x_red.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_4x_red.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_4x_white.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_4x_white.png +net.micode.notes.app-main-5\:/drawable-hdpi/widget_4x_yellow.png=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable-hdpi-v4\\widget_4x_yellow.png +net.micode.notes.app-main-5\:/drawable/new_note.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\drawable\\new_note.xml +net.micode.notes.app-main-5\:/layout/account_dialog_title.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\account_dialog_title.xml +net.micode.notes.app-main-5\:/layout/add_account_text.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\add_account_text.xml +net.micode.notes.app-main-5\:/layout/datetime_picker.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\datetime_picker.xml +net.micode.notes.app-main-5\:/layout/dialog_edit_text.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\dialog_edit_text.xml +net.micode.notes.app-main-5\:/layout/folder_list_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\folder_list_item.xml +net.micode.notes.app-main-5\:/layout/note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_edit.xml +net.micode.notes.app-main-5\:/layout/note_edit_list_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_edit_list_item.xml +net.micode.notes.app-main-5\:/layout/note_item.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_item.xml +net.micode.notes.app-main-5\:/layout/note_list.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_list.xml +net.micode.notes.app-main-5\:/layout/note_list_dropdown_menu.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_list_dropdown_menu.xml +net.micode.notes.app-main-5\:/layout/note_list_footer.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\note_list_footer.xml +net.micode.notes.app-main-5\:/layout/settings_header.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\settings_header.xml +net.micode.notes.app-main-5\:/layout/widget_2x.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\widget_2x.xml +net.micode.notes.app-main-5\:/layout/widget_4x.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\layout\\widget_4x.xml +net.micode.notes.app-main-5\:/menu/call_note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\call_note_edit.xml +net.micode.notes.app-main-5\:/menu/call_record_folder.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\call_record_folder.xml +net.micode.notes.app-main-5\:/menu/note_edit.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\note_edit.xml +net.micode.notes.app-main-5\:/menu/note_list.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\note_list.xml +net.micode.notes.app-main-5\:/menu/note_list_dropdown.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\note_list_dropdown.xml +net.micode.notes.app-main-5\:/menu/note_list_options.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\note_list_options.xml +net.micode.notes.app-main-5\:/menu/sub_folder.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\menu\\sub_folder.xml +net.micode.notes.app-main-5\:/raw-zh-rCN/introduction=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\raw-zh-rCN\\introduction +net.micode.notes.app-main-5\:/raw/introduction=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\raw\\introduction +net.micode.notes.app-main-5\:/xml/preferences.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\xml\\preferences.xml +net.micode.notes.app-main-5\:/xml/searchable.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\xml\\searchable.xml +net.micode.notes.app-main-5\:/xml/widget_2x_info.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\xml\\widget_2x_info.xml +net.micode.notes.app-main-5\:/xml/widget_4x_info.xml=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\packaged_res\\debug\\xml\\widget_4x_info.xml diff --git a/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml new file mode 100644 index 0000000..0102458 --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml @@ -0,0 +1,169 @@ + + + + -%s + --%s + --%s + --%s + + + Messaging + Email + + #335b5b5b + 26sp + 20sp + 17sp + 14sp + 33sp + + %1$s result for \"%2$s\" + + %1$s results for \"%2$s\" + + Confirm to delete folder and its notes? + Confirm to delete this note? + Confirm to delete the selected %d notes? + Delete selected notes + Notes + Notes 2x2 + Notes 4x4 + Delete + Call notes + cancel + set + Delete reminder successfully + Sorry, can not set clock on empty note + Sorry, can not send and empty note to home + The note is not exist + Export failed, please check SD card + SD card busy, not available now + Sync is canceled + Sync failed, internal error occurs + Sync failed, please check network and account settings + Export fail + notes_%s.txt + /MIUI/notes/ + The folder %1$s exist, please rename + yyyyMMdd + MMMd kk:mm + Export text file (%1$s) to SD (%2$s) directory + (%d) + Have moved selected %1$d notes to %2$s folder + Input name + Note added to home + Remind me + New Folder + Delete + Deselect all + Export text + Change folder name + Delete folder + View folder + Large + Medium + Font size + Small + Super + Enter check list + Move to folder + Parent folder + Leave check list + Delete reminder + Search + Select all + Nothing selected, the operation is invalid + %d selected + Send to home + Settings + Share + Sync + Cancel syncing + Select folder + Expired + Send email + Open map + Call + Browse web + Take a look + Got it + Add note + ... + Sync notes with google task + Sync account + Add account + New note background color random + Cancel syncing + Sync immediately + Current account %1$s + All sync related information will be deleted, which may result in duplicated items sometime + Please select a google account. Local notes will be synced with google task. + Sync notes + Last sync time %1$s + yyyy-MM-dd hh:mm:ss + Cancel + Change sync account + Remove sync account + Settings + Cannot change the account because sync is in progress + %1$s has been set as the sync account + Notes + Search notes + Searching Notes + Text in your notes + Set reminder + Export successful + Sync is successful with account %1$s + Getting remote note list... + Logging into %1$s... + Synchronize local notes with Google Task... + Sync is canceled + Sync is failed + Sync is successful + Syncing notes... + No associated note found, click to create associated note. + Privacy mode,can not see note content + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merger.xml b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merger.xml new file mode 100644 index 0000000..5a13304 --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/debug/packageDebugResources/merger.xml @@ -0,0 +1,56 @@ + + + -%s + --%s + --%s + --%s + + Messaging + Email + #335b5b5b33sp26sp20sp17sp14spNotesNotes 2x2Notes 4x4No associated note found, click to create associated note.Privacy mode,can not see note content...Add noteDelete reminder successfullySet reminderExpiredyyyyMMddMMMd kk:mmGot itTake a lookCallSend emailBrowse webOpen map/MIUI/notes/notes_%s.txt(%d)New FolderExport textSyncCancel syncingSettingsSearchDeleteMove to folder%d selectedNothing selected, the operation is invalidSelect allDeselect allFont sizeSmallMediumLargeSuperEnter check listLeave check listView folderDelete folderChange folder nameThe folder %1$s exist, please renameShareSend to homeRemind meDelete reminderSelect folderParent folderNote added to homeConfirm to delete folder and its notes?Delete selected notesConfirm to delete the selected %d notes?Confirm to delete this note?Have moved selected %1$d notes to %2$s folderSD card busy, not available nowExport failed, please check SD cardThe note is not existSorry, can not set clock on empty noteSorry, can not send and empty note to homeExport successfulExport failExport text file (%1$s) to SD (%2$s) directorySyncing notes...Sync is successfulSync is failedSync is canceledSync is successful with account %1$sSync failed, please check network and account settingsSync failed, internal error occursSync is canceledLogging into %1$s...Getting remote note list...Synchronize local notes with Google Task...SettingsSync accountSync notes with google taskLast sync time %1$syyyy-MM-dd hh:mm:ssAdd accountChange sync accountRemove sync accountCancelSync immediatelyCancel syncingCurrent account %1$sAll sync related information will be deleted, which may result in duplicated items sometimeSync notesPlease select a google account. Local notes will be synced with google task.Cannot change the account because sync is in progress%1$s has been set as the sync accountNew note background color randomDeleteCall notesInput nameSearching NotesSearch notesText in your notesNotessetcancel + %1$s result for \"%2$s\" + + %1$s results for \"%2$s\" + + 短信 + 邮件 + 便签便签2x2便签4x4没有关联内容,点击新建便签。访客模式下,便签内容不可见...新建便签成功删除提醒创建提醒已过期yyyyMMddMM月dd日 kk:mm知道了查看呼叫电话发送邮件浏览网页打开地图新建文件夹导出文本同步取消同步设置搜索删除移动到文件夹选中了 %d 项没有选中项,操作无效全选取消全选文字大小正常超大进入清单模式退出清单模式查看文件夹刪除文件夹修改文件夹名称文件夹 %1$s 已存在,请重新命名分享发送到桌面提醒我删除提醒选择文件夹上一级文件夹已添加到桌面删除确认要删除所选的 %d 条便签吗?确认要删除该条便签吗?确认删除文件夹及所包含的便签吗?已将所选 %1$d 条便签移到 %2$s 文件夹SD卡被占用,不能操作导出文本时发生错误,请检查SD卡要查看的便签不存在不能为空便签设置闹钟提醒不能将空便签发送到桌面导出成功导出失败已将文本文件(%1$s)输出至SD卡(%2$s)目录同步便签...同步成功同步失败同步已取消与%1$s同步成功同步失败,请检查网络和帐号设置同步失败,发生内部错误同步已取消登录%1$s...正在获取服务器便签列表...正在同步本地便签...设置同步账号与google task同步便签记录上次同步于 %1$s添加账号更换账号删除账号取消立即同步取消同步当前帐号 %1$s如更换同步帐号,过去的帐号同步信息将被清空,再次切换的同时可能会造成数据重复同步便签请选择google帐号,便签将与该帐号的google task内容同步。正在同步中,不能修改同步帐号同步帐号已设置为%1$s新建便签背景颜色随机删除通话便签请输入名称正在搜索便签搜索便签便签中的文字便签设置取消 + %1$s 条符合“%2$s”的搜索结果 + + 短信 + 郵件 + 便簽便簽2x2便簽4x4沒有關聯內容,點擊新建便簽。訪客模式下,便籤內容不可見...新建便簽成功刪除提醒創建提醒已過期yyyyMMddMM月dd日 kk:mm知道了查看呼叫電話發送郵件浏覽網頁打開地圖已將所選 %1$d 便籤移到 %2$s 文件夾新建文件夾導出文本同步取消同步設置搜尋刪除移動到文件夾選中了 %d 項沒有選中項,操作無效全選取消全選文字大小正常超大進入清單模式退出清單模式查看文件夾刪除文件夾修改文件夾名稱文件夾 %1$s 已存在,請重新命名分享發送到桌面提醒我刪除提醒選擇文件夾上一級文件夾已添加到桌面刪除确认要刪除所選的 %d 條便籤嗎?确认要删除該條便籤嗎?確認刪除檔夾及所包含的便簽嗎?SD卡被佔用,不能操作導出TXT時發生錯誤,請檢查SD卡要查看的便籤不存在不能爲空便籤設置鬧鐘提醒不能將空便籤發送到桌面導出成功導出失敗已將文本文件(%1$s)導出至SD(%2$s)目錄同步便簽...同步成功同步失敗同步已取消與%1$s同步成功同步失敗,請檢查網絡和帳號設置同步失敗,發生內部錯誤同步已取消登陸%1$s...正在獲取服務器便籤列表...正在同步本地便籤...設置同步賬號与google task同步便簽記錄上次同步于 %1$s添加賬號更換賬號刪除賬號取消立即同步取消同步當前帳號 %1$s如更換同步帳號,過去的帳號同步信息將被清空,再次切換的同時可能會造成數據重復同步便簽請選擇google帳號,便簽將與該帳號的google task內容同步。正在同步中,不能修改同步帳號同步帳號已設置為%1$s新建便籤背景顏色隨機刪除通話便籤請輸入名稱正在搜索便籤搜索便籤便籤中的文字便籤設置取消 + %1$s 條符合”%2$s“的搜尋結果 + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt b/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt new file mode 100644 index 0000000..f56ec38 --- /dev/null +++ b/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/dex-renamer-state.txt @@ -0,0 +1,4 @@ +#Fri Dec 22 19:43:32 CST 2023 +base.0=D\:\\Study\\SE\\MiNotes\\src\\Notes\\app\\build\\intermediates\\dex\\debug\\mergeDexDebug\\classes.dex +path.0=classes.dex +renamed.0=classes.dex diff --git a/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/zip-cache/androidResources b/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/zip-cache/androidResources new file mode 100644 index 0000000..8106485 Binary files /dev/null and b/src/Notes/app/build/intermediates/incremental/packageDebug/tmp/debug/zip-cache/androidResources differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Contact.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Contact.class new file mode 100644 index 0000000..bac2d9e Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Contact.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$CallNote.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$CallNote.class new file mode 100644 index 0000000..3afa321 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$CallNote.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$DataConstants.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$DataConstants.class new file mode 100644 index 0000000..dc242b5 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$DataConstants.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$TextNote.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$TextNote.class new file mode 100644 index 0000000..009e6aa Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes$TextNote.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes.class new file mode 100644 index 0000000..65a3efc Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/Notes.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/NotesProvider.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/NotesProvider.class new file mode 100644 index 0000000..f99eef0 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/data/NotesProvider.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note$NoteData.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note$NoteData.class new file mode 100644 index 0000000..f1d00ac Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note$NoteData.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note.class new file mode 100644 index 0000000..fc87525 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/Note.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/WorkingNote.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/WorkingNote.class new file mode 100644 index 0000000..88b628d Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/model/WorkingNote.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmAlertActivity.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmAlertActivity.class new file mode 100644 index 0000000..c1d88a5 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmAlertActivity.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmInitReceiver.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmInitReceiver.class new file mode 100644 index 0000000..d3e4981 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmInitReceiver.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmReceiver.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmReceiver.class new file mode 100644 index 0000000..7118088 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/AlarmReceiver.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$1.class new file mode 100644 index 0000000..4e3869d Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$2.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$2.class new file mode 100644 index 0000000..57c1d4f Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$2.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$3.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$3.class new file mode 100644 index 0000000..8a7f8a0 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$3.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$4.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$4.class new file mode 100644 index 0000000..7bf0d6b Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker$4.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker.class new file mode 100644 index 0000000..f185cd1 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePicker.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog$1.class new file mode 100644 index 0000000..277fe40 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog.class new file mode 100644 index 0000000..aaf3a90 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DateTimePickerDialog.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu$1.class new file mode 100644 index 0000000..7c0d343 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu.class new file mode 100644 index 0000000..03c8ea0 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/DropdownMenu.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter$FolderListItem.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter$FolderListItem.class new file mode 100644 index 0000000..445ccf4 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter$FolderListItem.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter.class new file mode 100644 index 0000000..3b93e5e Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/FoldersListAdapter.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$1.class new file mode 100644 index 0000000..aecdf92 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$2.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$2.class new file mode 100644 index 0000000..ea8b2ac Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$2.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$3.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$3.class new file mode 100644 index 0000000..72aee1f Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$3.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.class new file mode 100644 index 0000000..770d355 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity.class new file mode 100644 index 0000000..b73d823 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditActivity.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText$1.class new file mode 100644 index 0000000..ec15e9e Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText.class new file mode 100644 index 0000000..eb8ca51 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NoteEditText.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$1.class new file mode 100644 index 0000000..55719be Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$2.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$2.class new file mode 100644 index 0000000..7bf36f7 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$2.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$3.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$3.class new file mode 100644 index 0000000..98a649c Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$3.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$4.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$4.class new file mode 100644 index 0000000..e28e197 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$4.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$5.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$5.class new file mode 100644 index 0000000..09164c1 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$5.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$6.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$6.class new file mode 100644 index 0000000..568cece Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$6.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$7.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$7.class new file mode 100644 index 0000000..950a358 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$7.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$8.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$8.class new file mode 100644 index 0000000..b1ecc29 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$8.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$9.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$9.class new file mode 100644 index 0000000..649a9d5 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$9.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.class new file mode 100644 index 0000000..bd775e5 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ListEditState.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ListEditState.class new file mode 100644 index 0000000..8b436df Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ListEditState.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$1.class new file mode 100644 index 0000000..5b7c24d Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$2.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$2.class new file mode 100644 index 0000000..004bb5a Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback$2.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback.class new file mode 100644 index 0000000..8ed8a58 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$ModeCallback.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.class new file mode 100644 index 0000000..3afadbf Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.class new file mode 100644 index 0000000..2699bd3 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity.class new file mode 100644 index 0000000..0223718 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListActivity.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.class new file mode 100644 index 0000000..5c2072b Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter.class new file mode 100644 index 0000000..0dfa320 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListAdapter.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListItem.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListItem.class new file mode 100644 index 0000000..99150f6 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesListItem.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$1.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$1.class new file mode 100644 index 0000000..4d5c288 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$1.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$2.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$2.class new file mode 100644 index 0000000..47c78ef Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$2.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$3.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$3.class new file mode 100644 index 0000000..baa7752 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$3.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$4.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$4.class new file mode 100644 index 0000000..1cc346a Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$4.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$5.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$5.class new file mode 100644 index 0000000..320d722 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$5.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$6.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$6.class new file mode 100644 index 0000000..0f88f2b Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$6.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$7.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$7.class new file mode 100644 index 0000000..4691731 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$7.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$8.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$8.class new file mode 100644 index 0000000..56f7e5c Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$8.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.class new file mode 100644 index 0000000..8329599 Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.class differ diff --git a/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity.class b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity.class new file mode 100644 index 0000000..6c4e83e Binary files /dev/null and b/src/Notes/app/build/intermediates/javac/debug/classes/net/micode/notes/ui/NotesPreferenceActivity.class differ diff --git a/src/Notes/app/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt b/src/Notes/app/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt new file mode 100644 index 0000000..2d292cc --- /dev/null +++ b/src/Notes/app/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt @@ -0,0 +1,287 @@ +1 +2 +17 +21 +22 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:5-44 +23 android:minSdkVersion="14" +23-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:15-41 +24 android:targetSdkVersion="29" /> +25 +26 +26-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:25:5-81 +26-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:25:22-78 +27 +27-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:26:5-88 +27-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:26:22-85 +28 +28-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:27:5-67 +28-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:27:22-64 +29 +29-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:28:5-72 +29-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:28:22-69 +30 +30-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:29:5-74 +30-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:29:22-71 +31 +31-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:30:5-80 +31-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:30:22-77 +32 +32-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:31:5-71 +32-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:31:22-68 +33 +33-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:32:5-74 +33-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:32:22-71 +34 +34-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:33:5-81 +34-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:33:22-78 +35 +36 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:35:5-150:19 +37 android:debuggable="true" +38 android:extractNativeLibs="true" +39 android:icon="@drawable/icon_app" +39-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:36:9-42 +40 android:label="@string/app_name" +40-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:37:9-41 +41 android:testOnly="true" > +42 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:38:9-51:20 +43 android:name="net.micode.notes.ui.NotesListActivity" +43-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:39:13-49 +44 android:configChanges="keyboardHidden|orientation|screenSize" +44-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:41:13-74 +45 android:exported="true" +45-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:40:13-36 +46 android:label="@string/app_name" +46-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:42:13-45 +47 android:launchMode="singleTop" +47-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:43:13-43 +48 android:theme="@style/NoteTheme" +48-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:44:13-45 +49 android:windowSoftInputMode="adjustPan" > +49-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:45:13-52 +50 +50-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:47:13-50:29 +51 +51-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:48:17-69 +51-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:48:25-66 +52 +53 +53-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:49:17-77 +53-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:49:27-74 +54 +55 +56 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:53:9-82:20 +57 android:name="net.micode.notes.ui.NoteEditActivity" +57-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:54:13-48 +58 android:configChanges="keyboardHidden|orientation|screenSize" +58-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:55:13-74 +59 android:launchMode="singleTop" +59-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:56:13-43 +60 android:theme="@style/NoteTheme" > +60-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:57:13-45 +61 +61-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:59:13-64:29 +62 +62-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:60:17-69 +62-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:60:25-66 +63 +64 +64-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:17-76 +64-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:27-73 +65 +66 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:17-167 +67 android:host="com.example.notes.provider" +67-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:101-142 +68 android:mimeType="vnd.android.cursor.item/text_note" +68-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:23-75 +69 android:path="/notes" +69-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:143-164 +70 android:scheme="content" /> +70-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:76-100 +71 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:17-167 +72 android:host="com.example.notes.provider" +72-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:101-142 +73 android:mimeType="vnd.android.cursor.item/call_note" +73-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:23-75 +74 android:path="/notes" +74-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:143-164 +75 android:scheme="content" /> +75-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:76-100 +76 +77 +77-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:67:13-72:29 +78 +78-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:68:17-79 +78-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:68:25-76 +79 +80 +80-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:17-76 +80-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:27-73 +81 +82 +82-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:17-167 +82-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:23-75 +83 +83-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:17-167 +83-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:23-75 +84 +85 +85-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:74:13-77:29 +86 +86-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:75:17-71 +86-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:75:25-68 +87 +88 +88-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:17-76 +88-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:27-73 +89 +90 +91 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:79:13-81:54 +92 android:name="android.app.searchable" +92-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:80:17-54 +93 android:resource="@xml/searchable" /> +93-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:81:17-51 +94 +95 +96 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:84:9-87:43 +97 android:name="net.micode.notes.data.NotesProvider" +97-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:85:13-63 +98 android:authorities="micode_notes" +98-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:86:13-47 +99 android:multiprocess="true" /> +99-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:87:13-40 +100 +101 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:89:9-101:20 +102 android:name="net.micode.notes.widget.NoteWidgetProvider_2x" +102-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:90:13-57 +103 android:label="@string/app_widget2x2" > +103-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:91:13-50 +104 +104-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:92:13-96:29 +105 +105-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:17-84 +105-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:25-81 +106 +106-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:17-85 +106-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:25-82 +107 +107-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:17-85 +107-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:25-82 +108 +109 +110 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:98:13-100:58 +111 android:name="android.appwidget.provider" +111-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:99:17-58 +112 android:resource="@xml/widget_2x_info" /> +112-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:100:17-55 +113 +114 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:102:9-115:20 +115 android:name="net.micode.notes.widget.NoteWidgetProvider_4x" +115-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:103:13-57 +116 android:label="@string/app_widget4x4" > +116-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:104:13-50 +117 +117-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:92:13-96:29 +118 +118-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:17-84 +118-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:25-81 +119 +119-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:17-85 +119-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:25-82 +120 +120-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:17-85 +120-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:25-82 +121 +122 +123 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:98:13-100:58 +124 android:name="android.appwidget.provider" +124-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:99:17-58 +125 android:resource="@xml/widget_4x_info" /> +125-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:100:17-55 +126 +127 +127-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:117:9-121:20 +127-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:117:19-55 +128 +128-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:118:13-120:29 +129 +129-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:119:17-79 +129-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:119:25-76 +130 +131 +132 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:123:9-126:20 +133 android:name="net.micode.notes.ui.AlarmReceiver" +133-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:124:13-61 +134 android:process=":remote" > +134-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:125:13-38 +135 +136 +137 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:128:9-133:20 +138 android:name="net.micode.notes.ui.AlarmAlertActivity" +138-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:129:13-50 +139 android:label="@string/app_name" +139-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:130:13-45 +140 android:launchMode="singleInstance" +140-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:131:13-48 +141 android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" > +141-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:132:13-75 +142 +143 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:135:9-140:20 +144 android:name="net.micode.notes.ui.NotesPreferenceActivity" +144-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:136:13-71 +145 android:label="@string/preferences_title" +145-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:137:13-54 +146 android:launchMode="singleTop" +146-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:138:13-43 +147 android:theme="@android:style/Theme.Holo.Light" > +147-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:139:13-60 +148 +149 +150 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:142:9-145:19 +151 android:name="net.micode.notes.gtask.remote.GTaskSyncService" +151-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:143:13-74 +152 android:exported="false" > +152-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:144:13-37 +153 +154 +155 D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:147:9-149:52 +156 android:name="android.app.default_searchable" +156-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:148:13-58 +157 android:value=".ui.NoteEditActivity" /> +157-->D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:149:13-49 +158 +159 +160 diff --git a/src/Notes/app/build/intermediates/merged_manifest/debug/AndroidManifest.xml b/src/Notes/app/build/intermediates/merged_manifest/debug/AndroidManifest.xml new file mode 100644 index 0000000..10e3b54 --- /dev/null +++ b/src/Notes/app/build/intermediates/merged_manifest/debug/AndroidManifest.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/merged_manifests/debug/AndroidManifest.xml b/src/Notes/app/build/intermediates/merged_manifests/debug/AndroidManifest.xml new file mode 100644 index 0000000..10e3b54 --- /dev/null +++ b/src/Notes/app/build/intermediates/merged_manifests/debug/AndroidManifest.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/merged_res/debug/values_values.arsc.flat b/src/Notes/app/build/intermediates/merged_res/debug/values_values.arsc.flat new file mode 100644 index 0000000..577bcf3 Binary files /dev/null and b/src/Notes/app/build/intermediates/merged_res/debug/values_values.arsc.flat differ diff --git a/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/debug.json b/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/debug.json new file mode 100644 index 0000000..57244ef --- /dev/null +++ b/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/debug.json @@ -0,0 +1,272 @@ +{ + "logs": [ + { + "outputFile": "C:\\Users\\11\\.gradle\\daemon\\8.0\\net.micode.notes.app-merged_res-4:\\values-zh-rTW_values-zh-rTW.arsc.flat", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values-zh-rTW\\strings.xml", + "from": { + "startLines": "122,72,71,70,69,19,20,21,112,113,121,120,26,76,77,75,74,73,89,88,87,79,61,29,30,80,37,114,68,64,39,45,50,40,60,59,58,54,53,51,52,55,56,46,67,57,65,44,49,48,47,63,43,62,41,42,66,28,34,36,33,35,32,31,25,24,96,95,98,110,103,102,104,105,107,106,97,101,99,100,94,108,109,119,117,116,118,27,78,86,91,90,92,85,84,83,82,22,23", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "6629,3647,3580,3506,3455,846,887,936,6169,6215,6574,6523,1225,3911,3980,3851,3784,3720,4654,4593,4529,4114,3018,1398,1452,4169,1805,6273,3395,3178,1917,2204,2455,1971,2957,2903,2851,2652,2603,2507,2556,2699,2747,2248,3335,2798,3222,2160,2407,2350,2294,3122,2115,3079,2022,2064,3275,1346,1657,1755,1609,1707,1561,1515,1173,1119,5036,4976,5179,6092,5495,5425,5560,5639,5824,5750,5112,5369,5237,5303,4926,5929,6013,6484,6375,6326,6421,1288,4058,4469,4769,4710,4837,4420,4374,4325,4273,985,1052", + "endLines": "124,72,71,70,69,19,20,21,112,113,121,120,26,76,77,75,74,73,89,88,87,79,61,29,30,80,37,114,68,64,39,45,50,40,60,59,58,54,53,51,52,55,56,46,67,57,65,44,49,48,47,63,43,62,41,42,66,28,34,36,33,35,32,31,25,24,96,95,98,110,103,102,104,105,107,106,97,101,99,100,94,108,109,119,117,116,118,27,78,86,91,90,92,85,84,83,82,22,23", + "endColumns": "14,71,65,72,49,39,47,47,44,56,53,49,61,67,76,58,65,62,54,59,62,53,59,52,61,83,79,49,58,42,52,42,50,49,59,52,50,45,47,47,45,46,49,44,58,51,51,42,46,55,54,54,43,41,40,49,58,50,48,48,46,46,46,44,50,52,74,58,56,73,63,68,77,109,103,72,65,54,64,64,48,82,77,37,44,47,61,56,54,58,66,57,61,47,44,47,50,65,65", + "endOffsets": "6803,3714,3641,3574,3500,881,930,979,6209,6267,6623,6568,1282,3974,4052,3905,3845,3778,4704,4648,4587,4163,3073,1446,1509,4248,1880,6318,3449,3216,1965,2242,2501,2016,3012,2951,2897,2693,2646,2550,2597,2741,2792,2288,3389,2845,3269,2198,2449,2401,2344,3172,2154,3116,2058,2109,3329,1392,1701,1799,1651,1749,1603,1555,1219,1167,5106,5030,5231,6161,5554,5489,5633,5744,5923,5818,5173,5419,5297,5363,4970,6007,6086,6517,6415,6369,6478,1340,4108,4523,4831,4763,4894,4463,4414,4368,4319,1046,1113" + }, + "to": { + "startLines": "6,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "215,384,456,522,595,645,685,733,781,826,883,937,987,1049,1117,1194,1253,1319,1382,1437,1497,1560,1614,1674,1727,1789,1873,1953,2003,2062,2105,2158,2201,2252,2302,2362,2415,2466,2512,2560,2608,2654,2701,2751,2796,2855,2907,2959,3002,3049,3105,3160,3215,3259,3301,3342,3392,3451,3502,3551,3600,3647,3694,3741,3786,3837,3890,3965,4024,4081,4155,4219,4288,4366,4476,4580,4653,4719,4774,4839,4904,4953,5036,5114,5152,5197,5245,5307,5364,5419,5478,5545,5603,5665,5713,5758,5806,5857,5923", + "endLines": "8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106", + "endColumns": "14,71,65,72,49,39,47,47,44,56,53,49,61,67,76,58,65,62,54,59,62,53,59,52,61,83,79,49,58,42,52,42,50,49,59,52,50,45,47,47,45,46,49,44,58,51,51,42,46,55,54,54,43,41,40,49,58,50,48,48,46,46,46,44,50,52,74,58,56,73,63,68,77,109,103,72,65,54,64,64,48,82,77,37,44,47,61,56,54,58,66,57,61,47,44,47,50,65,65", + "endOffsets": "379,451,517,590,640,680,728,776,821,878,932,982,1044,1112,1189,1248,1314,1377,1432,1492,1555,1609,1669,1722,1784,1868,1948,1998,2057,2100,2153,2196,2247,2297,2357,2410,2461,2507,2555,2603,2649,2696,2746,2791,2850,2902,2954,2997,3044,3100,3155,3210,3254,3296,3337,3387,3446,3497,3546,3595,3642,3689,3736,3781,3832,3885,3960,4019,4076,4150,4214,4283,4361,4471,4575,4648,4714,4769,4834,4899,4948,5031,5109,5147,5192,5240,5302,5359,5414,5473,5540,5598,5660,5708,5753,5801,5852,5918,5984" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values-zh-rTW\\arrays.xml", + "from": { + "startLines": "18", + "startColumns": "4", + "startOffsets": "730", + "endLines": "21", + "endColumns": "19", + "endOffsets": "838" + }, + "to": { + "startLines": "2", + "startColumns": "4", + "startOffsets": "105", + "endLines": "5", + "endColumns": "19", + "endOffsets": "210" + } + } + ] + }, + { + "outputFile": "net.micode.notes.app-merged_res-4:/values_values.arsc.flat", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\dimens.xml", + "from": { + "startLines": "-1,-1,-1,-1,-1", + "startColumns": "-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "13,14,15,16,17", + "startColumns": "4,4,4,4,4", + "startOffsets": "477,529,582,635,687", + "endColumns": "51,52,52,51,51", + "endOffsets": "524,577,630,682,734" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\arrays.xml", + "from": { + "startLines": "-1,-1", + "startColumns": "-1,-1", + "startOffsets": "-1,-1" + }, + "to": { + "startLines": "2,8", + "startColumns": "4,4", + "startOffsets": "105,300", + "endLines": "7,11", + "endColumns": "19,19", + "endOffsets": "295,415" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\colors.xml", + "from": { + "startLines": "-1", + "startColumns": "-1", + "startOffsets": "-1" + }, + "to": { + "startLines": "12", + "startColumns": "4", + "startOffsets": "420", + "endColumns": "56", + "endOffsets": "472" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\strings.xml", + "from": { + "startLines": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", + "startColumns": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "18,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "739,1092,1188,1271,1367,1436,1479,1531,1583,1632,1695,1753,1804,1888,1982,2090,2161,2245,2328,2394,2477,2579,2640,2702,2753,2831,2884,2944,3049,3108,3210,3265,3336,3385,3443,3490,3549,3606,3677,3738,3795,3845,3897,3950,4000,4050,4110,4163,4229,4291,4354,4401,4456,4544,4602,4664,4714,4759,4802,4862,4929,4984,5039,5092,5139,5192,5248,5296,5351,5404,5488,5555,5619,5715,5789,5870,5959,6122,6266,6345,6420,6502,6561,6641,6721,6776,6898,7001,7042,7095,7152,7226,7291,7359,7445,7525,7594,7688,7747,7802,7864,7924,8034", + "endLines": "22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "1087,1183,1266,1362,1431,1474,1526,1578,1627,1690,1748,1799,1883,1977,2085,2156,2240,2323,2389,2472,2574,2635,2697,2748,2826,2879,2939,3044,3103,3205,3260,3331,3380,3438,3485,3544,3601,3672,3733,3790,3840,3892,3945,3995,4045,4105,4158,4224,4286,4349,4396,4451,4539,4597,4659,4709,4754,4797,4857,4924,4979,5034,5087,5134,5187,5243,5291,5346,5399,5483,5550,5614,5710,5784,5865,5954,6117,6261,6340,6415,6497,6556,6636,6716,6771,6893,6996,7037,7090,7147,7221,7286,7354,7440,7520,7589,7683,7742,7797,7859,7919,8029,8119" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\styles.xml", + "from": { + "startLines": "-1,-1,64,-1,-1,-1,-1,-1,-1,-1,-1", + "startColumns": "-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,2704,-1,-1,-1,-1,-1,-1,-1,-1", + "endLines": "-1,-1,67,-1,-1,-1,-1,-1,-1,-1,-1", + "endColumns": "-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1", + "endOffsets": "-1,-1,2913,-1,-1,-1,-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "125,129,133,137,140,144,148,152,156,160,164", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8124,8328,8539,8749,8909,9092,9277,9462,9665,9871,10054", + "endLines": "128,132,136,139,143,147,151,155,159,163,167", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "8323,8534,8744,8904,9087,9272,9457,9660,9866,10049,10250" + } + } + ] + }, + { + "outputFile": "C:\\Users\\11\\.gradle\\daemon\\8.0\\net.micode.notes.app-merged_res-4:\\values_values.arsc.flat", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\dimens.xml", + "from": { + "startLines": "19,20,21,22,18", + "startColumns": "4,4,4,4,4", + "startOffsets": "783,836,890,944,730", + "endColumns": "51,52,52,51,51", + "endOffsets": "830,884,938,991,777" + }, + "to": { + "startLines": "13,14,15,16,17", + "startColumns": "4,4,4,4,4", + "startOffsets": "477,529,582,635,687", + "endColumns": "51,52,52,51,51", + "endOffsets": "524,577,630,682,734" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\arrays.xml", + "from": { + "startLines": "19,26", + "startColumns": "4,4", + "startOffsets": "758,1073", + "endLines": "24,29", + "endColumns": "19,19", + "endOffsets": "1065,1191" + }, + "to": { + "startLines": "2,8", + "startColumns": "4,4", + "startOffsets": "105,300", + "endLines": "7,11", + "endColumns": "19,19", + "endOffsets": "295,415" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\colors.xml", + "from": { + "startLines": "18", + "startColumns": "4", + "startOffsets": "730", + "endColumns": "56", + "endOffsets": "782" + }, + "to": { + "startLines": "12", + "startColumns": "4", + "startOffsets": "420", + "endColumns": "56", + "endOffsets": "472" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\strings.xml", + "from": { + "startLines": "128,72,75,74,73,19,20,21,118,119,127,126,26,81,82,80,79,78,94,93,92,84,39,38,64,29,30,85,41,76,120,71,67,42,48,53,43,63,62,61,57,56,54,55,58,59,49,70,60,68,47,52,51,50,66,46,65,44,45,69,28,34,36,33,35,32,31,25,24,101,100,104,116,109,108,110,111,113,112,102,103,107,105,106,99,114,115,125,123,122,124,27,83,91,96,95,97,90,89,88,87,22,23", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8136,3970,4234,4137,4067,846,890,943,7624,7674,8077,8025,1308,4694,4789,4622,4537,4453,5668,5584,5481,4967,2043,1991,3461,1515,1569,5029,2138,4318,7738,3898,3649,2198,2519,2825,2257,3389,3327,3269,3043,2990,2885,2939,3094,3145,2567,3831,3206,3699,2471,2769,2680,2621,3586,2420,3540,2315,2359,3763,1459,1784,1894,1736,1840,1679,1630,1252,1198,6131,6063,6375,7525,6744,6662,6819,6909,7153,7073,6216,6292,6602,6440,6521,6007,7298,7421,7983,7854,7796,7908,1393,4898,5394,5805,5735,5886,5334,5278,5215,5154,996,1107", + "endLines": "132,72,75,74,73,19,20,21,118,119,127,126,26,81,82,80,79,78,94,93,92,84,39,38,64,29,30,85,41,76,120,71,67,42,48,53,43,63,62,61,57,56,54,55,58,59,49,70,60,68,47,52,51,50,66,46,65,44,45,69,28,34,36,33,35,32,31,25,24,101,100,104,116,109,108,110,111,113,112,102,103,107,105,106,99,114,115,125,123,122,124,27,83,91,96,95,97,90,89,88,87,22,23", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "8544,4061,4312,4228,4131,884,937,990,7668,7732,8130,8071,1387,4783,4892,4688,4616,4531,5729,5662,5578,5023,2100,2037,3534,1563,1624,5129,2192,4415,7788,3964,3693,2251,2561,2879,2309,3455,3383,3321,3088,3037,2933,2984,3139,3200,2615,3892,3263,3757,2513,2819,2763,2674,3643,2465,3580,2353,2414,3825,1509,1834,1942,1778,1888,1730,1673,1302,1246,6210,6125,6434,7616,6813,6738,6903,7067,7292,7147,6286,6369,6656,6515,6596,6057,7415,7519,8019,7902,7848,7977,1453,4961,5475,5880,5799,5975,5388,5328,5272,5209,1101,1192" + }, + "to": { + "startLines": "18,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "739,1092,1188,1271,1367,1436,1479,1531,1583,1632,1695,1753,1804,1888,1982,2090,2161,2245,2328,2394,2477,2579,2640,2702,2753,2831,2884,2944,3049,3108,3210,3265,3336,3385,3443,3490,3549,3606,3677,3738,3795,3845,3897,3950,4000,4050,4110,4163,4229,4291,4354,4401,4456,4544,4602,4664,4714,4759,4802,4862,4929,4984,5039,5092,5139,5192,5248,5296,5351,5404,5488,5555,5619,5715,5789,5870,5959,6122,6266,6345,6420,6502,6561,6641,6721,6776,6898,7001,7042,7095,7152,7226,7291,7359,7445,7525,7594,7688,7747,7802,7864,7924,8034", + "endLines": "22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "1087,1183,1266,1362,1431,1474,1526,1578,1627,1690,1748,1799,1883,1977,2085,2156,2240,2323,2389,2472,2574,2635,2697,2748,2826,2879,2939,3044,3103,3205,3260,3331,3380,3438,3485,3544,3601,3672,3733,3790,3840,3892,3945,3995,4045,4105,4158,4224,4286,4349,4396,4451,4539,4597,4659,4709,4754,4797,4857,4924,4979,5034,5087,5134,5187,5243,5291,5346,5399,5483,5550,5614,5710,5784,5865,5954,6117,6261,6340,6415,6497,6556,6636,6716,6771,6893,6996,7037,7090,7147,7221,7286,7354,7440,7520,7589,7683,7742,7797,7859,7919,8029,8119" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\styles.xml", + "from": { + "startLines": "50,55,64,60,22,26,30,35,40,18,45", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "2112,2322,2704,2539,917,1104,1293,1484,1693,730,1905", + "endLines": "53,58,67,62,25,29,33,38,43,21,48", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "2314,2531,2910,2696,1098,1287,1476,1685,1897,911,2104" + }, + "to": { + "startLines": "125,129,133,137,140,144,148,152,156,160,164", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8124,8328,8539,8746,8906,9089,9274,9459,9662,9868,10051", + "endLines": "128,132,136,139,143,147,151,155,159,163,167", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "8323,8534,8741,8901,9084,9269,9454,9657,9863,10046,10247" + } + } + ] + }, + { + "outputFile": "C:\\Users\\11\\.gradle\\daemon\\8.0\\net.micode.notes.app-merged_res-4:\\values-zh-rCN_values-zh-rCN.arsc.flat", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values-zh-rCN\\strings.xml", + "from": { + "startLines": "121,71,70,69,68,19,20,21,112,113,120,119,26,77,78,76,75,74,90,89,88,80,60,29,30,81,72,114,67,63,38,44,49,39,59,58,57,53,52,50,51,54,55,45,66,56,64,43,48,47,46,62,42,61,40,41,65,28,34,36,33,35,32,31,25,24,97,96,99,111,104,103,105,106,108,107,98,102,100,101,95,109,110,118,116,115,117,27,79,87,92,91,93,86,85,84,83,22,23", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "6653,3566,3499,3425,3374,846,887,936,6195,6241,6598,6547,1225,3938,4007,3878,3812,3748,4682,4621,4557,4141,2937,1398,1452,4196,3640,6299,3314,3097,1836,2123,2374,1890,2876,2822,2770,2571,2522,2426,2475,2618,2666,2167,3254,2717,3141,2079,2326,2269,2213,3041,2034,2998,1941,1983,3194,1346,1657,1755,1609,1707,1561,1515,1173,1119,5064,5004,5207,6120,5523,5453,5588,5667,5852,5778,5140,5397,5265,5331,4954,5957,6041,6508,6399,6350,6445,1288,4085,4497,4797,4738,4865,4448,4402,4353,4301,985,1052", + "endLines": "123,71,70,69,68,19,20,21,112,113,120,119,26,77,78,76,75,74,90,89,88,80,60,29,30,81,72,114,67,63,38,44,49,39,59,58,57,53,52,50,51,54,55,45,66,56,64,43,48,47,46,62,42,61,40,41,65,28,34,36,33,35,32,31,25,24,97,96,99,111,104,103,105,106,108,107,98,102,100,101,95,109,110,118,116,115,117,27,79,87,92,91,93,86,85,84,83,22,23", + "endColumns": "14,72,65,72,49,39,47,47,44,56,53,49,61,67,76,58,64,62,54,59,62,53,59,52,61,84,80,49,58,42,52,42,50,49,59,52,50,45,47,47,45,46,49,44,58,51,51,42,46,55,54,54,43,41,40,49,58,50,48,48,46,46,46,44,50,52,74,58,56,73,63,68,77,109,103,72,65,54,64,64,48,82,77,37,44,47,61,56,54,58,66,57,61,47,44,47,50,65,65", + "endOffsets": "6827,3634,3560,3493,3419,881,930,979,6235,6293,6647,6592,1282,4001,4079,3932,3872,3806,4732,4676,4615,4190,2992,1446,1509,4276,3716,6344,3368,3135,1884,2161,2420,1935,2931,2870,2816,2612,2565,2469,2516,2660,2711,2207,3308,2764,3188,2117,2368,2320,2263,3091,2073,3035,1977,2028,3248,1392,1701,1799,1651,1749,1603,1555,1219,1167,5134,5058,5259,6189,5582,5517,5661,5772,5951,5846,5201,5447,5325,5391,4998,6035,6114,6541,6439,6393,6502,1340,4135,4551,4859,4791,4922,4491,4442,4396,4347,1046,1113" + }, + "to": { + "startLines": "6,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "215,384,457,523,596,646,686,734,782,827,884,938,988,1050,1118,1195,1254,1319,1382,1437,1497,1560,1614,1674,1727,1789,1874,1955,2005,2064,2107,2160,2203,2254,2304,2364,2417,2468,2514,2562,2610,2656,2703,2753,2798,2857,2909,2961,3004,3051,3107,3162,3217,3261,3303,3344,3394,3453,3504,3553,3602,3649,3696,3743,3788,3839,3892,3967,4026,4083,4157,4221,4290,4368,4478,4582,4655,4721,4776,4841,4906,4955,5038,5116,5154,5199,5247,5309,5366,5421,5480,5547,5605,5667,5715,5760,5808,5859,5925", + "endLines": "8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106", + "endColumns": "14,72,65,72,49,39,47,47,44,56,53,49,61,67,76,58,64,62,54,59,62,53,59,52,61,84,80,49,58,42,52,42,50,49,59,52,50,45,47,47,45,46,49,44,58,51,51,42,46,55,54,54,43,41,40,49,58,50,48,48,46,46,46,44,50,52,74,58,56,73,63,68,77,109,103,72,65,54,64,64,48,82,77,37,44,47,61,56,54,58,66,57,61,47,44,47,50,65,65", + "endOffsets": "379,452,518,591,641,681,729,777,822,879,933,983,1045,1113,1190,1249,1314,1377,1432,1492,1555,1609,1669,1722,1784,1869,1950,2000,2059,2102,2155,2198,2249,2299,2359,2412,2463,2509,2557,2605,2651,2698,2748,2793,2852,2904,2956,2999,3046,3102,3157,3212,3256,3298,3339,3389,3448,3499,3548,3597,3644,3691,3738,3783,3834,3887,3962,4021,4078,4152,4216,4285,4363,4473,4577,4650,4716,4771,4836,4901,4950,5033,5111,5149,5194,5242,5304,5361,5416,5475,5542,5600,5662,5710,5755,5803,5854,5920,5986" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values-zh-rCN\\arrays.xml", + "from": { + "startLines": "18", + "startColumns": "4", + "startOffsets": "730", + "endLines": "21", + "endColumns": "19", + "endOffsets": "838" + }, + "to": { + "startLines": "2", + "startColumns": "4", + "startOffsets": "105", + "endLines": "5", + "endColumns": "19", + "endOffsets": "210" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/values.json b/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/values.json new file mode 100644 index 0000000..79e33e9 --- /dev/null +++ b/src/Notes/app/build/intermediates/merged_res_blame_folder/debug/out/multi-v2/values.json @@ -0,0 +1,186 @@ +{ + "logs": [ + { + "outputFile": "C:\\Users\\11\\.gradle\\daemon\\8.0\\net.micode.notes.app-mergeDebugResources-2:\\values\\values.xml", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\dimens.xml", + "from": { + "startLines": "19,20,21,22,18", + "startColumns": "4,4,4,4,4", + "startOffsets": "783,836,890,944,730", + "endColumns": "51,52,52,51,51", + "endOffsets": "830,884,938,991,777" + }, + "to": { + "startLines": "13,14,15,16,17", + "startColumns": "4,4,4,4,4", + "startOffsets": "477,529,582,635,687", + "endColumns": "51,52,52,51,51", + "endOffsets": "524,577,630,682,734" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\arrays.xml", + "from": { + "startLines": "19,26", + "startColumns": "4,4", + "startOffsets": "758,1073", + "endLines": "24,29", + "endColumns": "19,19", + "endOffsets": "1065,1191" + }, + "to": { + "startLines": "2,8", + "startColumns": "4,4", + "startOffsets": "105,300", + "endLines": "7,11", + "endColumns": "19,19", + "endOffsets": "295,415" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\colors.xml", + "from": { + "startLines": "18", + "startColumns": "4", + "startOffsets": "730", + "endColumns": "56", + "endOffsets": "782" + }, + "to": { + "startLines": "12", + "startColumns": "4", + "startOffsets": "420", + "endColumns": "56", + "endOffsets": "472" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\strings.xml", + "from": { + "startLines": "128,72,75,74,73,19,20,21,118,119,127,126,26,81,82,80,79,78,94,93,92,84,39,38,64,29,30,85,41,76,120,71,67,42,48,53,43,63,62,61,57,56,54,55,58,59,49,70,60,68,47,52,51,50,66,46,65,44,45,69,28,34,36,33,35,32,31,25,24,101,100,104,116,109,108,110,111,113,112,102,103,107,105,106,99,114,115,125,123,122,124,27,83,91,96,95,97,90,89,88,87,22,23", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8136,3970,4234,4137,4067,846,890,943,7624,7674,8077,8025,1308,4694,4789,4622,4537,4453,5668,5584,5481,4967,2043,1991,3461,1515,1569,5029,2138,4318,7738,3898,3649,2198,2519,2825,2257,3389,3327,3269,3043,2990,2885,2939,3094,3145,2567,3831,3206,3699,2471,2769,2680,2621,3586,2420,3540,2315,2359,3763,1459,1784,1894,1736,1840,1679,1630,1252,1198,6131,6063,6375,7525,6744,6662,6819,6909,7153,7073,6216,6292,6602,6440,6521,6007,7298,7421,7983,7854,7796,7908,1393,4898,5394,5805,5735,5886,5334,5278,5215,5154,996,1107", + "endLines": "132,72,75,74,73,19,20,21,118,119,127,126,26,81,82,80,79,78,94,93,92,84,39,38,64,29,30,85,41,76,120,71,67,42,48,53,43,63,62,61,57,56,54,55,58,59,49,70,60,68,47,52,51,50,66,46,65,44,45,69,28,34,36,33,35,32,31,25,24,101,100,104,116,109,108,110,111,113,112,102,103,107,105,106,99,114,115,125,123,122,124,27,83,91,96,95,97,90,89,88,87,22,23", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "8544,4061,4312,4228,4131,884,937,990,7668,7732,8130,8071,1387,4783,4892,4688,4616,4531,5729,5662,5578,5023,2100,2037,3534,1563,1624,5129,2192,4415,7788,3964,3693,2251,2561,2879,2309,3455,3383,3321,3088,3037,2933,2984,3139,3200,2615,3892,3263,3757,2513,2819,2763,2674,3643,2465,3580,2353,2414,3825,1509,1834,1942,1778,1888,1730,1673,1302,1246,6210,6125,6434,7616,6813,6738,6903,7067,7292,7147,6286,6369,6656,6515,6596,6057,7415,7519,8019,7902,7848,7977,1453,4961,5475,5880,5799,5975,5388,5328,5272,5209,1101,1192" + }, + "to": { + "startLines": "18,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "739,1092,1188,1271,1367,1436,1479,1531,1583,1632,1695,1753,1804,1888,1982,2090,2161,2245,2328,2394,2477,2579,2640,2702,2753,2831,2884,2944,3049,3108,3210,3265,3336,3385,3443,3490,3549,3606,3677,3738,3795,3845,3897,3950,4000,4050,4110,4163,4229,4291,4354,4401,4456,4544,4602,4664,4714,4759,4802,4862,4929,4984,5039,5092,5139,5192,5248,5296,5351,5404,5488,5555,5619,5715,5789,5870,5959,6122,6266,6345,6420,6502,6561,6641,6721,6776,6898,7001,7042,7095,7152,7226,7291,7359,7445,7525,7594,7688,7747,7802,7864,7924,8034", + "endLines": "22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "1087,1183,1266,1362,1431,1474,1526,1578,1627,1690,1748,1799,1883,1977,2085,2156,2240,2323,2389,2472,2574,2635,2697,2748,2826,2879,2939,3044,3103,3205,3260,3331,3380,3438,3485,3544,3601,3672,3733,3790,3840,3892,3945,3995,4045,4105,4158,4224,4286,4349,4396,4451,4539,4597,4659,4709,4754,4797,4857,4924,4979,5034,5087,5134,5187,5243,5291,5346,5399,5483,5550,5614,5710,5784,5865,5954,6117,6261,6340,6415,6497,6556,6636,6716,6771,6893,6996,7037,7090,7147,7221,7286,7354,7440,7520,7589,7683,7742,7797,7859,7919,8029,8119" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\styles.xml", + "from": { + "startLines": "50,55,64,60,22,26,30,35,40,18,45", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "2112,2322,2704,2539,917,1104,1293,1484,1693,730,1905", + "endLines": "53,58,67,62,25,29,33,38,43,21,48", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "2314,2531,2910,2696,1098,1287,1476,1685,1897,911,2104" + }, + "to": { + "startLines": "125,129,133,137,140,144,148,152,156,160,164", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8124,8328,8539,8746,8906,9089,9274,9459,9662,9868,10051", + "endLines": "128,132,136,139,143,147,151,155,159,163,167", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "8323,8534,8741,8901,9084,9269,9454,9657,9863,10046,10247" + } + } + ] + }, + { + "outputFile": "net.micode.notes.app-mergeDebugResources-2:/values/values.xml", + "map": [ + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\dimens.xml", + "from": { + "startLines": "-1,-1,-1,-1,-1", + "startColumns": "-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "13,14,15,16,17", + "startColumns": "4,4,4,4,4", + "startOffsets": "477,529,582,635,687", + "endColumns": "51,52,52,51,51", + "endOffsets": "524,577,630,682,734" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\arrays.xml", + "from": { + "startLines": "-1,-1", + "startColumns": "-1,-1", + "startOffsets": "-1,-1" + }, + "to": { + "startLines": "2,8", + "startColumns": "4,4", + "startOffsets": "105,300", + "endLines": "7,11", + "endColumns": "19,19", + "endOffsets": "295,415" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\colors.xml", + "from": { + "startLines": "-1", + "startColumns": "-1", + "startOffsets": "-1" + }, + "to": { + "startLines": "12", + "startColumns": "4", + "startOffsets": "420", + "endColumns": "56", + "endOffsets": "472" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\strings.xml", + "from": { + "startLines": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", + "startColumns": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "18,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "739,1092,1188,1271,1367,1436,1479,1531,1583,1632,1695,1753,1804,1888,1982,2090,2161,2245,2328,2394,2477,2579,2640,2702,2753,2831,2884,2944,3049,3108,3210,3265,3336,3385,3443,3490,3549,3606,3677,3738,3795,3845,3897,3950,4000,4050,4110,4163,4229,4291,4354,4401,4456,4544,4602,4664,4714,4759,4802,4862,4929,4984,5039,5092,5139,5192,5248,5296,5351,5404,5488,5555,5619,5715,5789,5870,5959,6122,6266,6345,6420,6502,6561,6641,6721,6776,6898,7001,7042,7095,7152,7226,7291,7359,7445,7525,7594,7688,7747,7802,7864,7924,8034", + "endLines": "22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124", + "endColumns": "14,95,82,95,68,42,51,51,48,62,57,50,83,93,107,70,83,82,65,82,101,60,61,50,77,52,59,104,58,101,54,70,48,57,46,58,56,70,60,56,49,51,52,49,49,59,52,65,61,62,46,54,87,57,61,49,44,42,59,66,54,54,52,46,52,55,47,54,52,83,66,63,95,73,80,88,162,143,78,74,81,58,79,79,54,121,102,40,52,56,73,64,67,85,79,68,93,58,54,61,59,109,89", + "endOffsets": "1087,1183,1266,1362,1431,1474,1526,1578,1627,1690,1748,1799,1883,1977,2085,2156,2240,2323,2389,2472,2574,2635,2697,2748,2826,2879,2939,3044,3103,3205,3260,3331,3380,3438,3485,3544,3601,3672,3733,3790,3840,3892,3945,3995,4045,4105,4158,4224,4286,4349,4396,4451,4539,4597,4659,4709,4754,4797,4857,4924,4979,5034,5087,5134,5187,5243,5291,5346,5399,5483,5550,5614,5710,5784,5865,5954,6117,6261,6340,6415,6497,6556,6636,6716,6771,6893,6996,7037,7090,7147,7221,7286,7354,7440,7520,7589,7683,7742,7797,7859,7919,8029,8119" + } + }, + { + "source": "D:\\Study\\SE\\MiNotes\\src\\Notes\\app\\src\\main\\res\\values\\styles.xml", + "from": { + "startLines": "-1,-1,64,-1,-1,-1,-1,-1,-1,-1,-1", + "startColumns": "-1,-1,4,-1,-1,-1,-1,-1,-1,-1,-1", + "startOffsets": "-1,-1,2704,-1,-1,-1,-1,-1,-1,-1,-1", + "endLines": "-1,-1,67,-1,-1,-1,-1,-1,-1,-1,-1", + "endColumns": "-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1", + "endOffsets": "-1,-1,2913,-1,-1,-1,-1,-1,-1,-1,-1" + }, + "to": { + "startLines": "125,129,133,137,140,144,148,152,156,160,164", + "startColumns": "4,4,4,4,4,4,4,4,4,4,4", + "startOffsets": "8124,8328,8539,8749,8909,9092,9277,9462,9665,9871,10054", + "endLines": "128,132,136,139,143,147,151,155,159,163,167", + "endColumns": "12,12,12,12,12,12,12,12,12,12,12", + "endOffsets": "8323,8534,8744,8904,9087,9272,9457,9660,9866,10049,10250" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/packaged_res/debug/values/values.xml b/src/Notes/app/build/intermediates/packaged_res/debug/values/values.xml new file mode 100644 index 0000000..0102458 --- /dev/null +++ b/src/Notes/app/build/intermediates/packaged_res/debug/values/values.xml @@ -0,0 +1,169 @@ + + + + -%s + --%s + --%s + --%s + + + Messaging + Email + + #335b5b5b + 26sp + 20sp + 17sp + 14sp + 33sp + + %1$s result for \"%2$s\" + + %1$s results for \"%2$s\" + + Confirm to delete folder and its notes? + Confirm to delete this note? + Confirm to delete the selected %d notes? + Delete selected notes + Notes + Notes 2x2 + Notes 4x4 + Delete + Call notes + cancel + set + Delete reminder successfully + Sorry, can not set clock on empty note + Sorry, can not send and empty note to home + The note is not exist + Export failed, please check SD card + SD card busy, not available now + Sync is canceled + Sync failed, internal error occurs + Sync failed, please check network and account settings + Export fail + notes_%s.txt + /MIUI/notes/ + The folder %1$s exist, please rename + yyyyMMdd + MMMd kk:mm + Export text file (%1$s) to SD (%2$s) directory + (%d) + Have moved selected %1$d notes to %2$s folder + Input name + Note added to home + Remind me + New Folder + Delete + Deselect all + Export text + Change folder name + Delete folder + View folder + Large + Medium + Font size + Small + Super + Enter check list + Move to folder + Parent folder + Leave check list + Delete reminder + Search + Select all + Nothing selected, the operation is invalid + %d selected + Send to home + Settings + Share + Sync + Cancel syncing + Select folder + Expired + Send email + Open map + Call + Browse web + Take a look + Got it + Add note + ... + Sync notes with google task + Sync account + Add account + New note background color random + Cancel syncing + Sync immediately + Current account %1$s + All sync related information will be deleted, which may result in duplicated items sometime + Please select a google account. Local notes will be synced with google task. + Sync notes + Last sync time %1$s + yyyy-MM-dd hh:mm:ss + Cancel + Change sync account + Remove sync account + Settings + Cannot change the account because sync is in progress + %1$s has been set as the sync account + Notes + Search notes + Searching Notes + Text in your notes + Set reminder + Export successful + Sync is successful with account %1$s + Getting remote note list... + Logging into %1$s... + Synchronize local notes with Google Task... + Sync is canceled + Sync is failed + Sync is successful + Syncing notes... + No associated note found, click to create associated note. + Privacy mode,can not see note content + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/processed_res/debug/out/resources-debug.ap_ b/src/Notes/app/build/intermediates/processed_res/debug/out/resources-debug.ap_ new file mode 100644 index 0000000..81398cf Binary files /dev/null and b/src/Notes/app/build/intermediates/processed_res/debug/out/resources-debug.ap_ differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Contact.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Contact.dex new file mode 100644 index 0000000..9cf68af Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Contact.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$CallNote.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$CallNote.dex new file mode 100644 index 0000000..0375c44 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$CallNote.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$DataConstants.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$DataConstants.dex new file mode 100644 index 0000000..e0e5d49 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$DataConstants.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$TextNote.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$TextNote.dex new file mode 100644 index 0000000..e6f4ff6 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes$TextNote.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes.dex new file mode 100644 index 0000000..cc7483c Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/Notes.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/NotesProvider.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/NotesProvider.dex new file mode 100644 index 0000000..03e60e2 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/data/NotesProvider.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note$NoteData.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note$NoteData.dex new file mode 100644 index 0000000..3e11789 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note$NoteData.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note.dex new file mode 100644 index 0000000..b69c737 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/Note.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/WorkingNote.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/WorkingNote.dex new file mode 100644 index 0000000..d9dbc59 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/model/WorkingNote.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmAlertActivity.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmAlertActivity.dex new file mode 100644 index 0000000..4f89a20 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmAlertActivity.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmInitReceiver.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmInitReceiver.dex new file mode 100644 index 0000000..661d592 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmInitReceiver.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmReceiver.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmReceiver.dex new file mode 100644 index 0000000..f38c6d2 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/AlarmReceiver.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$1.dex new file mode 100644 index 0000000..7ba57c0 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$2.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$2.dex new file mode 100644 index 0000000..9dec7a4 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$2.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$3.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$3.dex new file mode 100644 index 0000000..0287241 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$3.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$4.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$4.dex new file mode 100644 index 0000000..c98deff Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker$4.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker.dex new file mode 100644 index 0000000..e320810 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePicker.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog$1.dex new file mode 100644 index 0000000..157cf55 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog.dex new file mode 100644 index 0000000..785388d Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DateTimePickerDialog.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu$1.dex new file mode 100644 index 0000000..58dd91f Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu.dex new file mode 100644 index 0000000..997771d Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/DropdownMenu.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter$FolderListItem.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter$FolderListItem.dex new file mode 100644 index 0000000..b8c96b2 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter$FolderListItem.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter.dex new file mode 100644 index 0000000..31bec51 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/FoldersListAdapter.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$1.dex new file mode 100644 index 0000000..a9ab536 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$2.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$2.dex new file mode 100644 index 0000000..f812a15 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$2.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$3.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$3.dex new file mode 100644 index 0000000..6b72c9a Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$3.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.dex new file mode 100644 index 0000000..37f4f57 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity$HeadViewHolder.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity.dex new file mode 100644 index 0000000..bda3c37 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditActivity.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText$1.dex new file mode 100644 index 0000000..b7cd7c8 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText.dex new file mode 100644 index 0000000..f6616c3 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NoteEditText.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$1.dex new file mode 100644 index 0000000..9530b86 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$2.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$2.dex new file mode 100644 index 0000000..46c0582 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$2.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$3.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$3.dex new file mode 100644 index 0000000..c77c1af Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$3.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$4.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$4.dex new file mode 100644 index 0000000..174a744 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$4.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$5.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$5.dex new file mode 100644 index 0000000..1300b6a Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$5.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$6.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$6.dex new file mode 100644 index 0000000..435e61b Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$6.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$7.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$7.dex new file mode 100644 index 0000000..2c4a38c Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$7.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$8.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$8.dex new file mode 100644 index 0000000..65ff865 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$8.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$9.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$9.dex new file mode 100644 index 0000000..ab07440 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$9.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.dex new file mode 100644 index 0000000..76bd4b6 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$BackgroundQueryHandler.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ListEditState.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ListEditState.dex new file mode 100644 index 0000000..3fa4402 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ListEditState.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$1.dex new file mode 100644 index 0000000..87a4341 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$2.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$2.dex new file mode 100644 index 0000000..6192f15 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback$2.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback.dex new file mode 100644 index 0000000..7bcf861 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$ModeCallback.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.dex new file mode 100644 index 0000000..2cdf2cf Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$NewNoteOnTouchListener.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.dex new file mode 100644 index 0000000..0939499 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity$OnListItemClickListener.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity.dex new file mode 100644 index 0000000..2784a4f Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListActivity.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.dex new file mode 100644 index 0000000..871cef8 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter$AppWidgetAttribute.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter.dex new file mode 100644 index 0000000..531903c Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListAdapter.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListItem.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListItem.dex new file mode 100644 index 0000000..5b6a996 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesListItem.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$1.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$1.dex new file mode 100644 index 0000000..5e7e15e Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$1.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$2.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$2.dex new file mode 100644 index 0000000..3e96d87 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$2.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$3.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$3.dex new file mode 100644 index 0000000..881ce90 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$3.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$4.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$4.dex new file mode 100644 index 0000000..527a8fb Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$4.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$5.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$5.dex new file mode 100644 index 0000000..8314569 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$5.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$6.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$6.dex new file mode 100644 index 0000000..508384c Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$6.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$7.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$7.dex new file mode 100644 index 0000000..4d668cf Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$7.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$8.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$8.dex new file mode 100644 index 0000000..3fd85c8 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$8.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.dex new file mode 100644 index 0000000..83d6689 Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity$GTaskReceiver.dex differ diff --git a/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity.dex b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity.dex new file mode 100644 index 0000000..4e192fd Binary files /dev/null and b/src/Notes/app/build/intermediates/project_dex_archive/debug/out/net/micode/notes/ui/NotesPreferenceActivity.dex differ diff --git a/src/Notes/app/build/intermediates/signing_config_versions/debug/signing-config-versions.json b/src/Notes/app/build/intermediates/signing_config_versions/debug/signing-config-versions.json new file mode 100644 index 0000000..1920ca8 --- /dev/null +++ b/src/Notes/app/build/intermediates/signing_config_versions/debug/signing-config-versions.json @@ -0,0 +1 @@ +{"enableV1Signing":true,"enableV2Signing":false,"enableV3Signing":false,"enableV4Signing":false} \ No newline at end of file diff --git a/src/Notes/app/build/intermediates/stable_resource_ids_file/debug/stableIds.txt b/src/Notes/app/build/intermediates/stable_resource_ids_file/debug/stableIds.txt new file mode 100644 index 0000000..6e7247b --- /dev/null +++ b/src/Notes/app/build/intermediates/stable_resource_ids_file/debug/stableIds.txt @@ -0,0 +1,283 @@ +net.micode.notes:xml/preferences = 0x7f0c0000 +net.micode.notes:string/error_sdcard_unmounted = 0x7f0a0010 +net.micode.notes:style/TextAppearanceUnderMenuIcon = 0x7f0b000a +net.micode.notes:string/menu_deselect_all = 0x7f0a0022 +net.micode.notes:string/search = 0x7f0a0056 +net.micode.notes:string/search_setting_description = 0x7f0a0059 +net.micode.notes:style/TextAppearanceSuper = 0x7f0b0009 +net.micode.notes:string/preferences_title = 0x7f0a0053 +net.micode.notes:style/HighlightTextAppearanceSecondary = 0x7f0b0001 +net.micode.notes:string/preferences_last_sync_time = 0x7f0a004e +net.micode.notes:string/preferences_menu_change_account = 0x7f0a0051 +net.micode.notes:xml/widget_4x_info = 0x7f0c0003 +net.micode.notes:string/notealert_enter = 0x7f0a0040 +net.micode.notes:string/set_remind_time_message = 0x7f0a005a +net.micode.notes:string/menu_send_to_desktop = 0x7f0a0035 +net.micode.notes:id/account_dialog_subtitle = 0x7f050000 +net.micode.notes:menu/note_list = 0x7f070003 +net.micode.notes:string/sync_progress_login = 0x7f0a005e +net.micode.notes:string/note_link_other = 0x7f0a003d +net.micode.notes:string/preferences_toast_success_set_accout = 0x7f0a0055 +net.micode.notes:string/search_hint = 0x7f0a0057 +net.micode.notes:string/menu_normal_mode = 0x7f0a002f +net.micode.notes:string/menu_setting = 0x7f0a0036 +net.micode.notes:string/preferences_bg_random_appear_title = 0x7f0a0047 +net.micode.notes:string/preferences_dialog_change_account_title = 0x7f0a004a +net.micode.notes:id/navigation_bar = 0x7f05002f +net.micode.notes:string/note_alert_expired = 0x7f0a003b +net.micode.notes:id/ll_font_super = 0x7f05001f +net.micode.notes:dimen/text_font_size_large = 0x7f030000 +net.micode.notes:string/menu_share = 0x7f0a0037 +net.micode.notes:string/error_sync_network = 0x7f0a0013 +net.micode.notes:id/notes_list = 0x7f050035 +net.micode.notes:string/widget_under_visit_mode = 0x7f0a0065 +net.micode.notes:string/menu_font_small = 0x7f0a002a +net.micode.notes:string/menu_font_normal = 0x7f0a0028 +net.micode.notes:string/note_link_tel = 0x7f0a003e +net.micode.notes:string/menu_select_title = 0x7f0a0034 +net.micode.notes:style/TextAppearanceMedium = 0x7f0b0005 +net.micode.notes:id/menu_send_to_desktop = 0x7f050029 +net.micode.notes:string/preferences_last_sync_time_format = 0x7f0a004f +net.micode.notes:menu/call_note_edit = 0x7f070000 +net.micode.notes:id/preference_sync_button = 0x7f050037 +net.micode.notes:string/menu_search = 0x7f0a0031 +net.micode.notes:string/menu_font_size = 0x7f0a0029 +net.micode.notes:string/info_note_enter_desktop = 0x7f0a001e +net.micode.notes:style/TextAppearanceLarge = 0x7f0b0004 +net.micode.notes:string/menu_select_all = 0x7f0a0032 +net.micode.notes:string/note_link_email = 0x7f0a003c +net.micode.notes:string/preferences_dialog_change_account_warn_msg = 0x7f0a004b +net.micode.notes:xml/searchable = 0x7f0c0001 +net.micode.notes:string/menu_folder_change_name = 0x7f0a0024 +net.micode.notes:string/menu_sync_cancel = 0x7f0a0039 +net.micode.notes:string/menu_export_text = 0x7f0a0023 +net.micode.notes:string/menu_remove_remind = 0x7f0a0030 +net.micode.notes:string/menu_font_large = 0x7f0a0027 +net.micode.notes:menu/sub_folder = 0x7f070006 +net.micode.notes:layout/note_item = 0x7f060007 +net.micode.notes:string/datetime_dialog_cancel = 0x7f0a0009 +net.micode.notes:string/menu_create_folder = 0x7f0a0020 +net.micode.notes:drawable/widget_2x_red = 0x7f04003a +net.micode.notes:drawable/widget_4x_yellow = 0x7f040041 +net.micode.notes:string/format_date_ymd = 0x7f0a0018 +net.micode.notes:string/preferences_account_summary = 0x7f0a0044 +net.micode.notes:string/success_sdcard_export = 0x7f0a005b +net.micode.notes:string/format_move_notes_to_folder = 0x7f0a001c +net.micode.notes:string/delete_remind_time_message = 0x7f0a000b +net.micode.notes:string/file_name_txt_format = 0x7f0a0015 +net.micode.notes:drawable/new_note = 0x7f04002f +net.micode.notes:string/folder_exist = 0x7f0a0017 +net.micode.notes:id/note_edit_list = 0x7f050031 +net.micode.notes:string/failed_sdcard_export = 0x7f0a0014 +net.micode.notes:string/menu_select_none = 0x7f0a0033 +net.micode.notes:layout/widget_4x = 0x7f06000d +net.micode.notes:string/error_sync_cancelled = 0x7f0a0011 +net.micode.notes:layout/note_list_dropdown_menu = 0x7f060009 +net.micode.notes:drawable/list_red_single = 0x7f040023 +net.micode.notes:string/ticker_cancel = 0x7f0a0060 +net.micode.notes:style/TextAppearanceSecondaryItem = 0x7f0b0008 +net.micode.notes:drawable/widget_4x_green = 0x7f04003e +net.micode.notes:string/error_sdcard_export = 0x7f0a000f +net.micode.notes:string/note_link_web = 0x7f0a003f +net.micode.notes:id/menu_sync = 0x7f05002c +net.micode.notes:style/TextAppearancePrimaryItem = 0x7f0b0007 +net.micode.notes:xml/widget_2x_info = 0x7f0c0002 +net.micode.notes:string/error_note_empty_for_clock = 0x7f0a000c +net.micode.notes:id/tv_title = 0x7f05003f +net.micode.notes:string/menu_move_parent_folder = 0x7f0a002e +net.micode.notes:string/notealert_ok = 0x7f0a0041 +net.micode.notes:id/iv_bg_yellow_select = 0x7f050017 +net.micode.notes:style/TextAppearanceNormal = 0x7f0b0006 +net.micode.notes:string/button_delete = 0x7f0a0007 +net.micode.notes:string/preferences_menu_remove_account = 0x7f0a0052 +net.micode.notes:id/menu_list_mode = 0x7f050025 +net.micode.notes:string/app_widget2x2 = 0x7f0a0005 +net.micode.notes:string/ticker_fail = 0x7f0a0061 +net.micode.notes:string/app_name = 0x7f0a0004 +net.micode.notes:string/search_label = 0x7f0a0058 +net.micode.notes:string/preferences_dialog_select_account_tips = 0x7f0a004c +net.micode.notes:string/success_sync_account = 0x7f0a005c +net.micode.notes:drawable/widget_2x_yellow = 0x7f04003c +net.micode.notes:id/amPm = 0x7f050003 +net.micode.notes:string/preferences_account_title = 0x7f0a0045 +net.micode.notes:string/alert_title_delete = 0x7f0a0003 +net.micode.notes:string/widget_havenot_content = 0x7f0a0064 +net.micode.notes:string/hint_foler_name = 0x7f0a001d +net.micode.notes:id/menu_delete = 0x7f050021 +net.micode.notes:drawable/list_red_down = 0x7f040021 +net.micode.notes:string/menu_title_select_folder = 0x7f0a003a +net.micode.notes:string/alert_message_delete_note = 0x7f0a0001 +net.micode.notes:string/format_datetime_mdhm = 0x7f0a0019 +net.micode.notes:string/alert_message_delete_folder = 0x7f0a0000 +net.micode.notes:string/preferences_add_account = 0x7f0a0046 +net.micode.notes:string/menu_sync = 0x7f0a0038 +net.micode.notes:id/move = 0x7f05002e +net.micode.notes:string/datetime_dialog_ok = 0x7f0a000a +net.micode.notes:string/ticker_syncing = 0x7f0a0063 +net.micode.notes:id/menu_search = 0x7f050028 +net.micode.notes:drawable/menu_move = 0x7f04002e +net.micode.notes:raw/introduction = 0x7f090000 +net.micode.notes:menu/call_record_folder = 0x7f070001 +net.micode.notes:drawable/list_red_middle = 0x7f040022 +net.micode.notes:layout/widget_2x = 0x7f06000c +net.micode.notes:drawable/icon_app = 0x7f040015 +net.micode.notes:layout/note_list = 0x7f060008 +net.micode.notes:layout/note_edit = 0x7f060005 +net.micode.notes:drawable/list_background = 0x7f040016 +net.micode.notes:string/alert_message_delete_notes = 0x7f0a0002 +net.micode.notes:drawable/widget_2x_blue = 0x7f040038 +net.micode.notes:layout/folder_list_item = 0x7f060004 +net.micode.notes:string/sync_progress_init_list = 0x7f0a005d +net.micode.notes:layout/add_account_text = 0x7f060001 +net.micode.notes:id/btn_new_note = 0x7f050004 +net.micode.notes:id/widget_text = 0x7f050042 +net.micode.notes:id/widget_bg_image = 0x7f050041 +net.micode.notes:string/menu_folder_delete = 0x7f0a0025 +net.micode.notes:id/tv_name = 0x7f05003d +net.micode.notes:id/account_dialog_title = 0x7f050001 +net.micode.notes:id/tv_folder_name = 0x7f05003b +net.micode.notes:id/tv_alert_date = 0x7f05003a +net.micode.notes:color/primary_text_dark = 0x7f020000 +net.micode.notes:id/tv_time = 0x7f05003e +net.micode.notes:id/selection_menu = 0x7f050038 +net.micode.notes:id/ll_font_small = 0x7f05001e +net.micode.notes:id/note_title = 0x7f050034 +net.micode.notes:string/format_exported_file_location = 0x7f0a001a +net.micode.notes:id/note_bg_color_selector = 0x7f050030 +net.micode.notes:id/menu_share = 0x7f05002b +net.micode.notes:string/format_folder_files_count = 0x7f0a001b +net.micode.notes:id/menu_setting = 0x7f05002a +net.micode.notes:string/menu_move = 0x7f0a002d +net.micode.notes:id/date = 0x7f050007 +net.micode.notes:id/note_item = 0x7f050033 +net.micode.notes:drawable/font_size_selector_bg = 0x7f040012 +net.micode.notes:id/note_edit_view = 0x7f050032 +net.micode.notes:style/HighlightTextAppearancePrimary = 0x7f0b0000 +net.micode.notes:string/preferences_dialog_select_account_title = 0x7f0a004d +net.micode.notes:id/menu_font_size = 0x7f050024 +net.micode.notes:string/preferences_button_sync_cancel = 0x7f0a0048 +net.micode.notes:id/menu_alert = 0x7f050020 +net.micode.notes:string/error_note_not_exist = 0x7f0a000e +net.micode.notes:string/error_note_empty_for_send_to_desktop = 0x7f0a000d +net.micode.notes:id/minute = 0x7f05002d +net.micode.notes:id/ll_font_normal = 0x7f05001d +net.micode.notes:id/ll_font_large = 0x7f05001c +net.micode.notes:id/iv_super_select = 0x7f05001b +net.micode.notes:string/preferences_button_sync_immediately = 0x7f0a0049 +net.micode.notes:drawable/bg_color_btn_mask = 0x7f040001 +net.micode.notes:drawable/list_yellow_up = 0x7f04002c +net.micode.notes:id/iv_bg_white = 0x7f050014 +net.micode.notes:id/iv_medium_select = 0x7f050019 +net.micode.notes:string/ticker_success = 0x7f0a0062 +net.micode.notes:id/iv_large_select = 0x7f050018 +net.micode.notes:drawable/bg_btn_set_color = 0x7f040000 +net.micode.notes:id/iv_bg_yellow = 0x7f050016 +net.micode.notes:menu/note_edit = 0x7f070002 +net.micode.notes:drawable/list_white_down = 0x7f040025 +net.micode.notes:drawable/list_white_up = 0x7f040028 +net.micode.notes:id/iv_bg_green = 0x7f050010 +net.micode.notes:drawable/delete = 0x7f040004 +net.micode.notes:id/iv_bg_blue = 0x7f05000e +net.micode.notes:drawable/list_green_single = 0x7f04001f +net.micode.notes:id/iv_alert_icon = 0x7f05000d +net.micode.notes:drawable/list_yellow_single = 0x7f04002b +net.micode.notes:id/cb_edit_item = 0x7f050006 +net.micode.notes:id/font_size_selector = 0x7f05000b +net.micode.notes:color/user_query_highlight = 0x7f020002 +net.micode.notes:drawable/font_super = 0x7f040014 +net.micode.notes:drawable/edit_title_blue = 0x7f040009 +net.micode.notes:id/et_edit_text = 0x7f050009 +net.micode.notes:string/preferences_toast_cannot_change_account = 0x7f0a0054 +net.micode.notes:id/iv_bg_green_select = 0x7f050011 +net.micode.notes:id/menu_new_note = 0x7f050027 +net.micode.notes:drawable/clock = 0x7f040003 +net.micode.notes:array/menu_share_ways = 0x7f010001 +net.micode.notes:drawable/font_small = 0x7f040013 +net.micode.notes:id/btn_set_bg_color = 0x7f050005 +net.micode.notes:style/NoteTheme = 0x7f0b0003 +net.micode.notes:drawable/notification = 0x7f040033 +net.micode.notes:id/iv_bg_blue_select = 0x7f05000f +net.micode.notes:drawable/widget_4x_blue = 0x7f04003d +net.micode.notes:drawable/edit_title_white = 0x7f04000c +net.micode.notes:string/menu_delete = 0x7f0a0021 +net.micode.notes:drawable/list_footer_bg = 0x7f04001c +net.micode.notes:drawable/edit_red = 0x7f040008 +net.micode.notes:string/preferences_menu_cancel = 0x7f0a0050 +net.micode.notes:drawable/widget_2x_white = 0x7f04003b +net.micode.notes:drawable/font_large = 0x7f040010 +net.micode.notes:string/file_path = 0x7f0a0016 +net.micode.notes:string/menu_alert = 0x7f0a001f +net.micode.notes:drawable/title_alert = 0x7f040036 +net.micode.notes:drawable/list_green_down = 0x7f04001d +net.micode.notes:string/error_sync_internal = 0x7f0a0012 +net.micode.notes:drawable/search_result = 0x7f040034 +net.micode.notes:string/app_widget4x4 = 0x7f0a0006 +net.micode.notes:drawable/title_bar_bg = 0x7f040037 +net.micode.notes:drawable/selected = 0x7f040035 +net.micode.notes:plurals/search_results_title = 0x7f080000 +net.micode.notes:drawable/edit_title_green = 0x7f04000a +net.micode.notes:drawable/new_note_normal = 0x7f040030 +net.micode.notes:drawable/edit_white = 0x7f04000e +net.micode.notes:drawable/widget_2x_green = 0x7f040039 +net.micode.notes:id/iv_bg_red = 0x7f050012 +net.micode.notes:drawable/list_white_single = 0x7f040027 +net.micode.notes:id/delete = 0x7f050008 +net.micode.notes:layout/note_edit_list_item = 0x7f060006 +net.micode.notes:string/call_record_folder_name = 0x7f0a0008 +net.micode.notes:drawable/list_green_up = 0x7f040020 +net.micode.notes:id/prefenerece_sync_status_textview = 0x7f050036 +net.micode.notes:id/et_foler_name = 0x7f05000a +net.micode.notes:id/menu_delete_remind = 0x7f050022 +net.micode.notes:drawable/note_edit_color_selector_panel = 0x7f040032 +net.micode.notes:id/menu_export_text = 0x7f050023 +net.micode.notes:id/hour = 0x7f05000c +net.micode.notes:string/menu_folder_view = 0x7f0a0026 +net.micode.notes:drawable/dropdown_icon = 0x7f040005 +net.micode.notes:string/notelist_string_info = 0x7f0a0043 +net.micode.notes:drawable/list_blue_single = 0x7f040019 +net.micode.notes:drawable/list_white_middle = 0x7f040026 +net.micode.notes:id/tv_title_bar = 0x7f050040 +net.micode.notes:drawable/edit_title_red = 0x7f04000b +net.micode.notes:dimen/text_font_size_normal = 0x7f030002 +net.micode.notes:layout/dialog_edit_text = 0x7f060003 +net.micode.notes:color/secondary_text_dark = 0x7f020001 +net.micode.notes:drawable/list_folder = 0x7f04001b +net.micode.notes:drawable/list_green_middle = 0x7f04001e +net.micode.notes:string/sync_progress_syncing = 0x7f0a005f +net.micode.notes:drawable/font_normal = 0x7f040011 +net.micode.notes:drawable/list_blue_up = 0x7f04001a +net.micode.notes:id/iv_small_select = 0x7f05001a +net.micode.notes:drawable/list_blue_down = 0x7f040017 +net.micode.notes:drawable/edit_yellow = 0x7f04000f +net.micode.notes:drawable/list_yellow_down = 0x7f040029 +net.micode.notes:dimen/text_font_size_super = 0x7f030004 +net.micode.notes:drawable/edit_blue = 0x7f040006 +net.micode.notes:array/format_for_exported_note = 0x7f010000 +net.micode.notes:string/menu_list_mode = 0x7f0a002c +net.micode.notes:drawable/list_yellow_middle = 0x7f04002a +net.micode.notes:drawable/list_blue_middle = 0x7f040018 +net.micode.notes:dimen/text_font_size_medium = 0x7f030001 +net.micode.notes:drawable/new_note_pressed = 0x7f040031 +net.micode.notes:id/menu_new_folder = 0x7f050026 +net.micode.notes:id/sv_note_edit = 0x7f050039 +net.micode.notes:drawable/call_record = 0x7f040002 +net.micode.notes:drawable/edit_green = 0x7f040007 +net.micode.notes:id/action_select_all = 0x7f050002 +net.micode.notes:id/tv_modified_date = 0x7f05003c +net.micode.notes:id/iv_bg_white_select = 0x7f050015 +net.micode.notes:drawable/edit_title_yellow = 0x7f04000d +net.micode.notes:layout/note_list_footer = 0x7f06000a +net.micode.notes:string/menu_font_super = 0x7f0a002b +net.micode.notes:drawable/widget_4x_red = 0x7f04003f +net.micode.notes:layout/account_dialog_title = 0x7f060000 +net.micode.notes:string/notelist_menu_new = 0x7f0a0042 +net.micode.notes:drawable/menu_delete = 0x7f04002d +net.micode.notes:id/iv_bg_red_select = 0x7f050013 +net.micode.notes:menu/note_list_dropdown = 0x7f070004 +net.micode.notes:drawable/list_red_up = 0x7f040024 +net.micode.notes:layout/settings_header = 0x7f06000b +net.micode.notes:style/NoteActionBarStyle = 0x7f0b0002 +net.micode.notes:dimen/text_font_size_small = 0x7f030003 +net.micode.notes:layout/datetime_picker = 0x7f060002 +net.micode.notes:menu/note_list_options = 0x7f070005 +net.micode.notes:drawable/widget_4x_white = 0x7f040040 diff --git a/src/Notes/app/build/outputs/logs/manifest-merger-debug-report.txt b/src/Notes/app/build/outputs/logs/manifest-merger-debug-report.txt new file mode 100644 index 0000000..0439431 --- /dev/null +++ b/src/Notes/app/build/outputs/logs/manifest-merger-debug-report.txt @@ -0,0 +1,233 @@ +-- Merging decision tree log --- +manifest +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:18:1-151:12 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:18:1-151:12 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:18:1-151:12 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:18:1-151:12 + package + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:19:5-31 + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml + android:versionName + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:21:5-30 + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml + xmlns:android + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:18:11-69 + android:versionCode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:20:5-28 + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml +uses-sdk +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:5-44 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:5-44 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:5-44 + android:targetSdkVersion + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml + android:minSdkVersion + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:23:15-41 + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml +uses-permission#android.permission.WRITE_EXTERNAL_STORAGE +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:25:5-81 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:25:22-78 +uses-permission#com.android.launcher.permission.INSTALL_SHORTCUT +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:26:5-88 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:26:22-85 +uses-permission#android.permission.INTERNET +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:27:5-67 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:27:22-64 +uses-permission#android.permission.READ_CONTACTS +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:28:5-72 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:28:22-69 +uses-permission#android.permission.MANAGE_ACCOUNTS +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:29:5-74 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:29:22-71 +uses-permission#android.permission.AUTHENTICATE_ACCOUNTS +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:30:5-80 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:30:22-77 +uses-permission#android.permission.GET_ACCOUNTS +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:31:5-71 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:31:22-68 +uses-permission#android.permission.USE_CREDENTIALS +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:32:5-74 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:32:22-71 +uses-permission#android.permission.RECEIVE_BOOT_COMPLETED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:33:5-81 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:33:22-78 +application +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:35:5-150:19 +INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:35:5-150:19 + android:extractNativeLibs + INJECTED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:37:9-41 + android:icon + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:36:9-42 +activity#net.micode.notes.ui.NotesListActivity +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:38:9-51:20 + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:42:13-45 + android:launchMode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:43:13-43 + android:windowSoftInputMode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:45:13-52 + android:exported + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:40:13-36 + android:configChanges + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:41:13-74 + android:theme + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:44:13-45 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:39:13-49 +intent-filter#action:name:android.intent.action.MAIN+category:name:android.intent.category.LAUNCHER +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:47:13-50:29 +action#android.intent.action.MAIN +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:48:17-69 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:48:25-66 +category#android.intent.category.LAUNCHER +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:49:17-77 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:49:27-74 +activity#net.micode.notes.ui.NoteEditActivity +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:53:9-82:20 + android:launchMode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:56:13-43 + android:configChanges + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:55:13-74 + android:theme + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:57:13-45 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:54:13-48 +intent-filter#action:name:android.intent.action.VIEW+category:name:android.intent.category.DEFAULT+data:host:com.example.notes.provider+data:host:com.example.notes.provider+data:mimeType:vnd.android.cursor.item/call_note+data:mimeType:vnd.android.cursor.item/text_note+data:path:/notes+data:path:/notes+data:scheme:content+data:scheme:content +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:59:13-64:29 +action#android.intent.action.VIEW +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:60:17-69 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:60:25-66 +category#android.intent.category.DEFAULT +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:17-76 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:61:27-73 +data +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:17-167 + android:path + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:143-164 + android:host + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:101-142 + android:scheme + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:76-100 + android:mimeType + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:62:23-75 +intent-filter#action:name:android.intent.action.INSERT_OR_EDIT+category:name:android.intent.category.DEFAULT+data:mimeType:vnd.android.cursor.item/call_note+data:mimeType:vnd.android.cursor.item/text_note +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:67:13-72:29 +action#android.intent.action.INSERT_OR_EDIT +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:68:17-79 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:68:25-76 +intent-filter#action:name:android.intent.action.SEARCH+category:name:android.intent.category.DEFAULT +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:74:13-77:29 +action#android.intent.action.SEARCH +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:75:17-71 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:75:25-68 +meta-data#android.app.searchable +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:79:13-81:54 + android:resource + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:81:17-51 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:80:17-54 +provider#net.micode.notes.data.NotesProvider +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:84:9-87:43 + android:authorities + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:86:13-47 + android:multiprocess + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:87:13-40 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:85:13-63 +receiver#net.micode.notes.widget.NoteWidgetProvider_2x +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:89:9-101:20 + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:91:13-50 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:90:13-57 +intent-filter#action:name:android.appwidget.action.APPWIDGET_DELETED+action:name:android.appwidget.action.APPWIDGET_UPDATE+action:name:android.intent.action.PRIVACY_MODE_CHANGED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:92:13-96:29 +action#android.appwidget.action.APPWIDGET_UPDATE +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:17-84 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:93:25-81 +action#android.appwidget.action.APPWIDGET_DELETED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:17-85 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:94:25-82 +action#android.intent.action.PRIVACY_MODE_CHANGED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:17-85 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:95:25-82 +meta-data#android.appwidget.provider +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:98:13-100:58 + android:resource + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:100:17-55 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:99:17-58 +receiver#net.micode.notes.widget.NoteWidgetProvider_4x +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:102:9-115:20 + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:104:13-50 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:103:13-57 +receiver#net.micode.notes.ui.AlarmInitReceiver +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:117:9-121:20 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:117:19-55 +intent-filter#action:name:android.intent.action.BOOT_COMPLETED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:118:13-120:29 +action#android.intent.action.BOOT_COMPLETED +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:119:17-79 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:119:25-76 +receiver#net.micode.notes.ui.AlarmReceiver +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:123:9-126:20 + android:process + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:125:13-38 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:124:13-61 +activity#net.micode.notes.ui.AlarmAlertActivity +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:128:9-133:20 + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:130:13-45 + android:launchMode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:131:13-48 + android:theme + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:132:13-75 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:129:13-50 +activity#net.micode.notes.ui.NotesPreferenceActivity +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:135:9-140:20 + android:label + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:137:13-54 + android:launchMode + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:138:13-43 + android:theme + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:139:13-60 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:136:13-71 +service#net.micode.notes.gtask.remote.GTaskSyncService +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:142:9-145:19 + android:exported + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:144:13-37 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:143:13-74 +meta-data#android.app.default_searchable +ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:147:9-149:52 + android:value + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:149:13-49 + android:name + ADDED from D:\Study\SE\MiNotes\src\Notes\app\src\main\AndroidManifest.xml:148:13-58 diff --git a/src/Notes/app/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/src/Notes/app/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin new file mode 100644 index 0000000..8bdaa80 Binary files /dev/null and b/src/Notes/app/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ diff --git a/src/Notes/app/src/main/AndroidManifest.xml b/src/Notes/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c71be5b --- /dev/null +++ b/src/Notes/app/src/main/AndroidManifest.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Notes/app/src/main/java/net/micode/notes/data/Contact.java b/src/Notes/app/src/main/java/net/micode/notes/data/Contact.java new file mode 100644 index 0000000..d65c239 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/data/Contact.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.data;//属于data这个包 + +import android.content.Context; +import android.database.Cursor; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; +import android.telephony.PhoneNumberUtils; +import android.util.Log; + +import java.util.HashMap; +/** + * @Package: net.micode.notes.data + * @ClassName: Contact + * @Description: + * Contact类用于查询联系人信息并进行缓存。 + * 该类包含一个静态的HashMap作为缓存,存储电话号码和对应的联系人名字。 + * 通过调用getContact方法可以根据给定的电话号码查询联系人名字。 + * 如果缓存中已经存在该电话号码对应的联系人名字,则直接返回缓存中的结果,否则通过查询数据库获取联系人名字并更新缓存。 + * 该类还定义了一个私有的SQL筛选语句用于查询联系人信息。 + * 注意:该类是线程不安全的,如果需要在多线程环境下使用,请做好同步控制 + * @Author: YangYizhe + * @CreateDate: 12/17/2023 10:10 AM + * @Version: 1.0 + */ +public class Contact { + /** + * 作为缓存,存储电话号码和对应的联系人名字 + */ + private static HashMap sContactCache; + private static final String TAG = "Contact";//设置日志TAG标签 + + //查询联系人的SQL筛选语句 + private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + + " AND " + Data.RAW_CONTACT_ID + " IN " + + "(SELECT raw_contact_id " + + " FROM phone_lookup" + + " WHERE min_match = '+')"; + //获取联系人 + public static String getContact(Context context, String phoneNumber) { + if(sContactCache == null) {/*如果缓存为空,就新建一个*/ + sContactCache = new HashMap(); + } + + if(sContactCache.containsKey(phoneNumber)) {/*如果缓存中已经有该电话号码对应的联系人名字,就直接返回*/ + return sContactCache.get(phoneNumber); + } + + String selection = CALLER_ID_SELECTION.replace("+", + PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));//将电话号码转换为最小匹配模式,用于筛选 + Cursor cursor = context.getContentResolver().query( + Data.CONTENT_URI, + new String [] { Phone.DISPLAY_NAME }, + selection,//使用筛选条件 + new String[] { phoneNumber }, + null); + + if (cursor != null && cursor.moveToFirst()) {//如果找到了符合条件的联系人 + try { + String name = cursor.getString(0);//获取联系人名字 + sContactCache.put(phoneNumber, name);//将电话号码和联系人名字添加到缓存中 + return name;//返回联系人名字 + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, " Cursor get string error " + e.toString()); + return null; + } finally { + cursor.close();//关闭游标 + } + } else {/*没找到*/ + Log.d(TAG, "No contact matched with number:" + phoneNumber); + return null; + } + } +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/model/Note.java b/src/Notes/app/src/main/java/net/micode/notes/model/Note.java new file mode 100644 index 0000000..864da2c --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/model/Note.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.model; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.OperationApplicationException; +import android.net.Uri; +import android.os.RemoteException; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.Notes.TextNote; + +import java.util.ArrayList; + +/** + * @Package: net.micode.notes.model + * @ClassName: Note + * @Description: 笔记类,用于操作和管理笔记数据 + * @Author: YangYizhe + * @CreateDate: 12/17/2023 10:06 AM + * @UpdateUser: none + * @UpdateDate: 12/17/2023 10:06 AM + * @UpdateRemark: none + * @Version: 1.0 + */ +public class Note { + private ContentValues mNoteDiffValues; + private NoteData mNoteData; + private static final String TAG = "Note"; + /** + * @method getNewNoteId + * @description 获取新的笔记ID,用于向数据库中添加新的笔记 + * @date: 12/20/2023 11:23 PM + * @author: YangYizhe + * @param folderId 文件夹Id + * @return noteId 新的笔记Id + */ + public static synchronized long getNewNoteId(Context context, long folderId) { + // Create a new note in the database + // 在数据库中创建一个新的笔记 + ContentValues values = new ContentValues(); + long createdTime = System.currentTimeMillis(); + values.put(NoteColumns.CREATED_DATE, createdTime); + values.put(NoteColumns.MODIFIED_DATE, createdTime); + values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + values.put(NoteColumns.PARENT_ID, folderId); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); + + long noteId = 0; + try { + noteId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "Get note id error :" + e.toString()); + noteId = 0; + } + if (noteId == -1) { + throw new IllegalStateException("Wrong note id:" + noteId); + } + return noteId; + } + + public Note() { + mNoteDiffValues = new ContentValues(); + mNoteData = new NoteData(); + } + /** + * @method setNoteValue + * @description 设置笔记的值 + * @date: 12/20/2023 11:31 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setNoteValue(String key, String value) { + mNoteDiffValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + /** + * @method setTextData + * @description 设置文本数据 + * @date: 12/20/2023 11:31 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setTextData(String key, String value) { + mNoteData.setTextData(key, value); + } + /** + * @method setTextDataId + * @description 设置文本数据ID + * @date: 12/20/2023 11:33 PM + * @author: YangYizhe + * @param id + */ + public void setTextDataId(long id) { + mNoteData.setTextDataId(id); + } + /** + * @method getTextDataId + * @description 获取文本数据Id + * @date: 12/20/2023 11:34 PM + * @author: YangYizhe + * @return mTextDataId 文本数据Id + */ + public long getTextDataId() { + return mNoteData.mTextDataId; + } + /** + * @method setCallDataId + * @description 设置通话记录数据ID + * @date: 12/20/2023 11:35 PM + * @author: YangYizhe + * @param id 通话记录数据id + */ + public void setCallDataId(long id) { + mNoteData.setCallDataId(id); + } + /** + * @method setCallData + * @description 设置通话记录数据 + * @date: 12/20/2023 11:36 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setCallData(String key, String value) { + mNoteData.setCallData(key, value); + } + /** + * @method isLocalModified + * @description 判断笔记是否有本地修改 + * @date: 12/20/2023 11:38 PM + * @author: YangYizhe + * @return bool 是否有本地修改 + */ + public boolean isLocalModified() { + return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); + } + /** + * @method syncNote + * @description 同步笔记,将本地修改的数据同步到服务器 + * @date: 12/20/2023 11:42 PM + * @author: YangYizhe + * @param context 上下文对象 + * @param noteId 笔记ID + * @return bool 是否同步成功 + */ + public boolean syncNote(Context context, long noteId) { + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + } + + if (!isLocalModified()) { + return true; + } + + /** + * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and + * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the + * note data info + */ + if (context.getContentResolver().update( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, + null) == 0) { + Log.e(TAG, "Update note error, should not happen"); + // Do not return, fall through + } + mNoteDiffValues.clear(); + + if (mNoteData.isLocalModified() + && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { + return false; + } + + return true; + } + + private class NoteData { + private long mTextDataId; + + private ContentValues mTextDataValues; + + private long mCallDataId; + + private ContentValues mCallDataValues; + + private static final String TAG = "NoteData"; + + public NoteData() { + mTextDataValues = new ContentValues(); + mCallDataValues = new ContentValues(); + mTextDataId = 0; + mCallDataId = 0; + } + + boolean isLocalModified() { + return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; + } + + void setTextDataId(long id) { + if(id <= 0) { + throw new IllegalArgumentException("Text data id should larger than 0"); + } + mTextDataId = id; + } + + void setCallDataId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("Call data id should larger than 0"); + } + mCallDataId = id; + } + + void setCallData(String key, String value) { + mCallDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + void setTextData(String key, String value) { + mTextDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + Uri pushIntoContentResolver(Context context, long noteId) { + /** + * Check for safety + */ + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + } + + ArrayList operationList = new ArrayList(); + ContentProviderOperation.Builder builder = null; + + if(mTextDataValues.size() > 0) { + mTextDataValues.put(DataColumns.NOTE_ID, noteId); + if (mTextDataId == 0) { + mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mTextDataValues); + try { + setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new text data fail with noteId" + noteId); + mTextDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mTextDataId)); + builder.withValues(mTextDataValues); + operationList.add(builder.build()); + } + mTextDataValues.clear(); + } + + if(mCallDataValues.size() > 0) { + mCallDataValues.put(DataColumns.NOTE_ID, noteId); + if (mCallDataId == 0) { + mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mCallDataValues); + try { + setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new call data fail with noteId" + noteId); + mCallDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mCallDataId)); + builder.withValues(mCallDataValues); + operationList.add(builder.build()); + } + mCallDataValues.clear(); + } + + if (operationList.size() > 0) { + try { + ContentProviderResult[] results = context.getContentResolver().applyBatch( + Notes.AUTHORITY, operationList); + return (results == null || results.length == 0 || results[0] == null) ? null + : ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId); + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } + } + return null; + } + } +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/model/WorkingNote.java b/src/Notes/app/src/main/java/net/micode/notes/model/WorkingNote.java new file mode 100644 index 0000000..31061f9 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.model; + +import android.appwidget.AppWidgetManager; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.Notes.TextNote; +import net.micode.notes.tool.ResourceParser.NoteBgResources; + +/** + * @Package: net.micode.notes.model + * @ClassName: WorkingNote + * @Description: + * 工作笔记类,用于表示一条工作笔记的信息 + * Note 类是一个基本的笔记类,包含了笔记的基本信息,如标题、内容等 + * WorkingNote 类则是在 Note 类的基础上进行扩展,增加了一些与工作笔记相关的属性和方法,例如提醒日期、背景颜色、小部件等。 + * @Author: YangYizhe + * @CreateDate: 12/20/2023 11:48 PM + * @Version: 1.0 + */ +public class WorkingNote { + // Note for the working note + private Note mNote; + // Note Id + private long mNoteId; + // Note content + private String mContent; + // Note mode + private int mMode; + + private long mAlertDate; + + private long mModifiedDate; + + private int mBgColorId; + + private int mWidgetId; + + private int mWidgetType; + + private long mFolderId; + + private Context mContext; + + private static final String TAG = "WorkingNote"; + + private boolean mIsDeleted; + /** + * 笔记设置状态变化监听器 + */ + private NoteSettingChangedListener mNoteSettingStatusListener; + + public static final String[] DATA_PROJECTION = new String[] { + DataColumns.ID, + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + public static final String[] NOTE_PROJECTION = new String[] { + NoteColumns.PARENT_ID, + NoteColumns.ALERTED_DATE, + NoteColumns.BG_COLOR_ID, + NoteColumns.WIDGET_ID, + NoteColumns.WIDGET_TYPE, + NoteColumns.MODIFIED_DATE + }; + + private static final int DATA_ID_COLUMN = 0; + + private static final int DATA_CONTENT_COLUMN = 1; + + private static final int DATA_MIME_TYPE_COLUMN = 2; + + private static final int DATA_MODE_COLUMN = 3; + + private static final int NOTE_PARENT_ID_COLUMN = 0; + + private static final int NOTE_ALERTED_DATE_COLUMN = 1; + + private static final int NOTE_BG_COLOR_ID_COLUMN = 2; + + private static final int NOTE_WIDGET_ID_COLUMN = 3; + + private static final int NOTE_WIDGET_TYPE_COLUMN = 4; + + private static final int NOTE_MODIFIED_DATE_COLUMN = 5; + + // New note construct + /** + * @method WorkingNote + * @description 构造方法,创建一个新的工作笔记 + * @date: 12/20/2023 11:54 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param folderId 笔记所属的文件夹ID + */ + private WorkingNote(Context context, long folderId) { + mContext = context; + mAlertDate = 0; + mModifiedDate = System.currentTimeMillis(); + mFolderId = folderId; + mNote = new Note(); + mNoteId = 0; + mIsDeleted = false; + mMode = 0; + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + } + /** + * @method WorkingNote + * @description 构造方法,加载一个已存在的工作笔记 + * @date: 12/20/2023 11:54 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param noteId 笔记的ID + * @param folderId 笔记所属的文件夹ID + */ + // Existing note construct + private WorkingNote(Context context, long noteId, long folderId) { + mContext = context; + mNoteId = noteId; + mFolderId = folderId; + mIsDeleted = false; + mNote = new Note(); + loadNote(); + } + /** + * @method loadNote + * @description 加载笔记的详细信息 + * @date: 12/20/2023 11:55 PM + * @author: YangYizhe + */ + private void loadNote() { + Cursor cursor = mContext.getContentResolver().query( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, + null, null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); + mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); + mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); + mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); + mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); + mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); + } + cursor.close(); + } else { + Log.e(TAG, "No note with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note with id " + mNoteId); + } + loadNoteData(); + } + /** + * @method loadNoteData + * @description 加载笔记的Data + * @date: 12/20/2023 11:55 PM + * @author: YangYizhe + */ + private void loadNoteData() { + Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, + DataColumns.NOTE_ID + "=?", new String[] { + String.valueOf(mNoteId) + }, null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + String type = cursor.getString(DATA_MIME_TYPE_COLUMN); + if (DataConstants.NOTE.equals(type)) { + mContent = cursor.getString(DATA_CONTENT_COLUMN); + mMode = cursor.getInt(DATA_MODE_COLUMN); + mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); + } else if (DataConstants.CALL_NOTE.equals(type)) { + mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); + } else { + Log.d(TAG, "Wrong note type with type:" + type); + } + } while (cursor.moveToNext()); + } + cursor.close(); + } else { + Log.e(TAG, "No data with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); + } + } + /** + * @method createEmptyNote + * @description 创建一个空的工作笔记 + * @date: 12/20/2023 11:56 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param folderId 笔记所属的文件夹ID + * @param widgetId 笔记的小部件ID + * @param widgetType 笔记的小部件类型 + * @param defaultBgColorId 笔记的默认背景颜色ID + * @return note 创建的空的工作笔记对象 + */ + public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, + int widgetType, int defaultBgColorId) { + WorkingNote note = new WorkingNote(context, folderId); + note.setBgColorId(defaultBgColorId); + note.setWidgetId(widgetId); + note.setWidgetType(widgetType); + return note; + } + + public static WorkingNote load(Context context, long id) { + return new WorkingNote(context, id, 0); + } + + public synchronized boolean saveNote() { + if (isWorthSaving()) { + if (!existInDatabase()) { + if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { + Log.e(TAG, "Create new note fail with id:" + mNoteId); + return false; + } + } + + mNote.syncNote(mContext, mNoteId); + + /** + * Update widget content if there exist any widget of this note + */ + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + return true; + } else { + return false; + } + } + + public boolean existInDatabase() { + return mNoteId > 0; + } + + private boolean isWorthSaving() { + if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) + || (existInDatabase() && !mNote.isLocalModified())) { + return false; + } else { + return true; + } + } + + public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { + mNoteSettingStatusListener = l; + } + + public void setAlertDate(long date, boolean set) { + if (date != mAlertDate) { + mAlertDate = date; + mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate)); + } + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onClockAlertChanged(date, set); + } + } + + public void markDeleted(boolean mark) { + mIsDeleted = mark; + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + } + + public void setBgColorId(int id) { + if (id != mBgColorId) { + mBgColorId = id; + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onBackgroundColorChanged(); + } + mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); + } + } + + public void setCheckListMode(int mode) { + if (mMode != mode) { + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); + } + mMode = mode; + mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); + } + } + + public void setWidgetType(int type) { + if (type != mWidgetType) { + mWidgetType = type; + mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); + } + } + + public void setWidgetId(int id) { + if (id != mWidgetId) { + mWidgetId = id; + mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); + } + } + + public void setWorkingText(String text) { + if (!TextUtils.equals(mContent, text)) { + mContent = text; + mNote.setTextData(DataColumns.CONTENT, mContent); + } + } + + public void convertToCallNote(String phoneNumber, long callDate) { + mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); + mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); + mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); + } + + public boolean hasClockAlert() { + return (mAlertDate > 0 ? true : false); + } + + public String getContent() { + return mContent; + } + + public long getAlertDate() { + return mAlertDate; + } + + public long getModifiedDate() { + return mModifiedDate; + } + + public int getBgColorResId() { + return NoteBgResources.getNoteBgResource(mBgColorId); + } + + public int getBgColorId() { + return mBgColorId; + } + + public int getTitleBgResId() { + return NoteBgResources.getNoteTitleBgResource(mBgColorId); + } + + public int getCheckListMode() { + return mMode; + } + + public long getNoteId() { + return mNoteId; + } + + public long getFolderId() { + return mFolderId; + } + + public int getWidgetId() { + return mWidgetId; + } + + public int getWidgetType() { + return mWidgetType; + } + + public interface NoteSettingChangedListener { + /** + * Called when the background color of current note has just changed + */ + void onBackgroundColorChanged(); + + /** + * Called when user set clock + */ + void onClockAlertChanged(long date, boolean set); + + /** + * Call when user create note from widget + */ + void onWidgetChanged(); + + /** + * Call when switch between check list mode and normal mode + * @param oldMode is previous mode before change + * @param newMode is new mode + */ + void onCheckListModeChanged(int oldMode, int newMode); + } +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java new file mode 100644 index 0000000..96f28bf --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -0,0 +1,201 @@ +package net.micode.notes.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface.OnDismissListener; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.Window; +import android.view.WindowManager; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; + +import java.io.IOException; +/** + * @Package: net.micode.notes.ui + * @ClassName: AlarmAlertActivity + * @Description: 闹钟提醒界面 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:02 AM + * @Version: 1.0 + */ +public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + private long mNoteId; //文本在数据库存储中的ID号 + private String mSnippet; //闹钟提示时出现的文本片段 + private static final int SNIPPET_PREW_MAX_LEN = 60; + MediaPlayer mPlayer; + /** + * @method onCreate + * @description 当 Activity 创建时调用的生命周期方法 + * @date: 12/21/2023 12:05 AM + * @author: YangYizhe + * @param savedInstanceState 保存 Activity 状态的 Bundle 对象 + * @return null + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_NO_TITLE);//设置界面显示——无标题 + + final Window win = getWindow(); + + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);//设置窗体属性——在锁屏时显示 + + if (!isScreenOn()) { + win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON//保持点亮、点亮屏幕、允许点亮时解锁 + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); + } + + Intent intent = getIntent();//获取传递的 Intent + + try { + // 从 Intent 中获取数据并处理——获取标签 ID + mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + // 根据 ID 从数据库中获取标签内容 + mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + // 判断标签片段是否达到符合长度 + mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, + SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) + : mSnippet; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return; + } + + mPlayer = new MediaPlayer(); + if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + showActionDialog();// 显示对话框 + playAlarmSound();// 播放闹钟提示音 + } else { + finish();// 结束当前 Activity + } + } + /** + * @method isScreenOn + * @description + * 判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型 + * @date: 12/23/2023 11:21 PM + * @author: YangYizhe + * @param + * @return + */ + private boolean isScreenOn() { + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + return pm.isScreenOn(); + } + /** + * @method playAlarmSound + * @description + * 播放闹钟提示音 + * @date: 12/23/2023 11:21 PM + * @author: YangYizhe + */ + private void playAlarmSound() { + Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + //调用系统的铃声管理URI,得到闹钟提示音 + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + + if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { + mPlayer.setAudioStreamType(silentModeStreams); + } else { + mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + } + try { + mPlayer.setDataSource(this, url); + mPlayer.prepare(); + mPlayer.setLooping(true);//设置是否循环播放 + mPlayer.start();//开始播放 + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + /** + * @method showActionDialog + * @description + * AlertDialog的构造方法全部是Protected的 + * 所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。 + * 要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法 + * 如这里的dialog就是新建了一个AlertDialog + * @date: 12/23/2023 11:28 PM + * @author: YangYizhe + */ + private void showActionDialog() { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(R.string.app_name);//为对话框设置标题 + dialog.setMessage(mSnippet);//为对话框设置内容 + dialog.setPositiveButton(R.string.notealert_ok, this);//给对话框添加"Yes"按钮 + if (isScreenOn()) { + dialog.setNegativeButton(R.string.notealert_enter, this);//对话框添加"No"按钮 + } + dialog.show().setOnDismissListener(this); + } + /** + * @method onClick + * @description 处理点击事件 + * @date: 12/23/2023 11:27 PM + * @author: YangYizhe + * @param dialog + * @param which + */ + public void onClick(DialogInterface dialog, int which) { + switch (which) {//用which来选择click后下一步的操作 + case DialogInterface.BUTTON_NEGATIVE://这是取消操作 + Intent intent = new Intent(this, NoteEditActivity.class);//实现两个类间的数据传输 + intent.setAction(Intent.ACTION_VIEW);//设置动作属性 + intent.putExtra(Intent.EXTRA_UID, mNoteId);//实现key-value对 EXTRA_UID为key;mNoteId为键 + startActivity(intent);//开始动作 + break; + default: + break; + } + } + /** + * @method onDismiss + * @description 忽略 + * @date: 12/23/2023 11:25 PM + * @author: YangYizhe + * @param dialog + */ + public void onDismiss(DialogInterface dialog) { + stopAlarmSound();//停止闹钟声音 + finish(); + } + /** + * @method stopAlarmSound + * @description 停止闹钟的声音 + * @date: 12/23/2023 11:26 PM + * @author: YangYizhe + */ + private void stopAlarmSound() { + if (mPlayer != null) { + mPlayer.stop();//停止播放 + mPlayer.release();//释放MediaPlayer对象 + mPlayer = null; + } + } +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java new file mode 100644 index 0000000..1982fda --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -0,0 +1,57 @@ +package net.micode.notes.ui; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; + +/** + * @Package: net.micode.notes.ui + * @ClassName: AlarmInitReceiver + * @Description: + * AlarmInitReceiver 是一个广播接收器(BroadcastReceiver)的类 + * 广播接收器是 Android 中常用的一种组件,用于接收并处理系统或应用发送的广播消息 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:09 AM + * @Version: 1.0 + */ +public class AlarmInitReceiver extends BroadcastReceiver { + private static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.ALERTED_DATE + };//对数据库的操作,调用标签ID和闹钟时间 + private static final int COLUMN_ID = 0; + private static final int COLUMN_ALERTED_DATE = 1; + + @Override + public void onReceive(Context context, Intent intent) { + long currentDate = System.currentTimeMillis();//System.currentTimeMillis()产生一个当前的毫秒 + Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, + new String[] { String.valueOf(currentDate) }, + null);//将long变量currentDate转化为字符串 + //Cursor在这里的作用是通过查找数据库中的标签内容,找到和当前系统时间相等的标签 + + if (c != null) { + if (c.moveToFirst()) { + do { + long alertDate = c.getLong(COLUMN_ALERTED_DATE); + Intent sender = new Intent(context, AlarmReceiver.class); + sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + AlarmManager alermManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); + } while (c.moveToNext()); + } + c.close(); + } + } +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java new file mode 100644 index 0000000..646f69f --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/AlarmReceiver.java @@ -0,0 +1,25 @@ +package net.micode.notes.ui; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +/** + * @Package: net.micode.notes.ui + * @ClassName: AlarmReceiver + * @Description: 闹钟接收器,接收到闹钟触发的广播后启动AlarmAlertActivity进行闹钟提醒 + * @Author: YangYizhe + * @CreateDate: 12/17/2023 10:02 AM + * @UpdateUser: none + * @UpdateDate: 12/17/2023 10:02 AM + * @UpdateRemark: none + * @Version: 1.0 + */ +public class AlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + intent.setClass(context, AlarmAlertActivity.class);//启动AlarmAlertActivity + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent);//启动闹钟提醒界面 + } +} + \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java new file mode 100644 index 0000000..9cf4ba6 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -0,0 +1,518 @@ +package net.micode.notes.ui; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + +import net.micode.notes.R; + + +import android.content.Context; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.NumberPicker; +/** + * @Package: net.micode.notes.ui + * @ClassName: DateTimePicker + * @Description: 继承自FrameLayout,实现了日期和时间的选择功能 + * 提供一个用户界面,让用户可以方便地选择日期和时间,并且能够监听用户对日期和时间的改变 + * 构造方法,包括默认构造方法和带参数的构造方法,用于初始化日期选择器的界面和属性; + * 一系列的回调方法,用于监听日期和时间的改变,包括日期选择、小时选择、分钟选择、上午/下午选择等; + * 一些公开的接口方法,用于设置当前日期、时间,设置24小时模式或12小时模式的切换等; + * 辅助方法,用于更新日期、小时、上午/下午选择器的界面显示和属性; + * 回调接口OnDateTimeChangedListener,用于监听日期和时间的改变事件。 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:18 AM + * @Version: 1.0 + */ +public class DateTimePicker extends FrameLayout { + //FrameLayout是布局模板之一 + private static final boolean DEFAULT_ENABLE_STATE = true; + + private static final int HOURS_IN_HALF_DAY = 12; + private static final int HOURS_IN_ALL_DAY = 24; + private static final int DAYS_IN_ALL_WEEK = 7; + private static final int DATE_SPINNER_MIN_VAL = 0; + private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; + private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; + private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; + private static final int MINUT_SPINNER_MIN_VAL = 0; + private static final int MINUT_SPINNER_MAX_VAL = 59; + private static final int AMPM_SPINNER_MIN_VAL = 0; + private static final int AMPM_SPINNER_MAX_VAL = 1; + /** + * 初始化控件 + * NumberPicker是数字选择器 + * 这里定义的四个变量全部是在设置闹钟时需要选择的变量(如日期、时、分、上午或者下午) + */ + private final NumberPicker mDateSpinner; + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private Calendar mDate;//定义了Calendar类型的变量mDate,用于操作时间 + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + private boolean mIsAm; + + private boolean mIs24HourView; + + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + private boolean mInitialising; + + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal); + updateDateControl(); + onDateTimeChanged(); + } + };//OnValueChangeListener,这是时间改变监听器,这里主要是对日期的监听 + + + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + //这里是对 小时(Hour) 的监听 + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + boolean isDateChanged = false; + Calendar cal = Calendar.getInstance(); + //声明一个Calendar的变量cal,便于后续的操作 + if (!mIs24HourView) { + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + //这里是对于12小时制时,晚上11点和12点交替时对日期的更改 + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || + oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + }//这里是对于12小时制时,中午11点和12点交替时对AM和PM的更改 + } else { + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + //这里是对于24小时制时,晚上11点和12点交替时对日期的更改 + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + } //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + //通过数字选择器对newHour的赋值 + mDate.set(Calendar.HOUR_OF_DAY, newHour); + //通过set函数将新的Hour值传给mDate + onDateTimeChanged(); + if (isDateChanged) { + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); + } + } + }; + + private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + //这里是对 分钟(Minute)改变的监听 + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + int offset = 0; + //设置offset,作为小时改变的一个记录数据 + if (oldVal == maxValue && newVal == minValue) { + offset += 1; + } else if (oldVal == minValue && newVal == maxValue) { + offset -= 1; + } + //如果原值为59,新值为0,则offset加1 + //如果原值为0,新值为59,则offset减1 + if (offset != 0) { + mDate.add(Calendar.HOUR_OF_DAY, offset); + mHourSpinner.setValue(getCurrentHour()); + updateDateControl(); + int newHour = getCurrentHourOfDay(); + if (newHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + updateAmPmControl(); + } else { + mIsAm = true; + updateAmPmControl(); + } + } + mDate.set(Calendar.MINUTE, newVal); + onDateTimeChanged(); + } + }; + + private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { + //对AM和PM的监听 + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mIsAm = !mIsAm; + if (mIsAm) { + mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); + } else { + mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); + } + updateAmPmControl(); + onDateTimeChanged(); + } + }; + + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + /** + * 构造方法 + */ + public DateTimePicker(Context context) { + this(context, System.currentTimeMillis());//通过对数据库的访问,获取当前的系统时间 + } + + public DateTimePicker(Context context, long date) { + this(context, date, DateFormat.is24HourFormat(context));//上面函数的得到的是一个天文数字(1970至今的秒数),需要DateFormat将其变得有意义 + } + + public DateTimePicker(Context context, long date, boolean is24HourView) { + super(context); + mDate = Calendar.getInstance();//获取系统时间 + mInitialising = true; + mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY; + inflate(context, R.layout.datetime_picker, this); + /* + * 如果当前Activity里用到别的layout,比如对话框layout + * 还要设置这个layout上的其他组件的内容,就必须用inflate()方法先将对话框的layout找出来 + * 然后再用findViewById()找到它上面的其它组件 + */ + mDateSpinner = (NumberPicker) findViewById(R.id.date); + mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); + mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); + mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); + + mHourSpinner = (NumberPicker) findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); + mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); + + String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); + mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); + mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); + mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); + mAmPmSpinner.setDisplayedValues(stringsForAmPm); + mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); + + // update controls to initial state + updateDateControl(); + updateHourControl(); + updateAmPmControl(); + + set24HourView(is24HourView); + + // set to current time + setCurrentDate(date); + + setEnabled(isEnabled()); + + // set the content descriptions + mInitialising = false; + } + + /** + * @method setEnabled + * @description + * 用于设置是否启用日期选择器控件的功能 + * 先通过传入的参数enabled判断是否需要改变控件的启用状态。 + * 如果传入的参数和当前的启用状态相同,则直接返回,不进行任何操作 + * 如果传入的参数和当前的启用状态不同,则调用父类的setEnabled方法,来设置整个日期选择器控件的启用状态 + * 分别设置日期选择、分钟选择、小时选择、上午/下午选择这几个子控件的启用状态,即调用对应的setEnabled方法,并将enabled参数传入 + * @date: 12/21/2023 12:27 AM + * @author: YangYizhe + * @param enabled + */ + @Override + public void setEnabled(boolean enabled) { + if (mIsEnabled == enabled) { + return; + } + super.setEnabled(enabled); + mDateSpinner.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + mHourSpinner.setEnabled(enabled); + mAmPmSpinner.setEnabled(enabled); + mIsEnabled = enabled; + } + @Override + public boolean isEnabled() { + return mIsEnabled; + } + + /** + * Get the current date in millis + * + * @return the current date in millis + */ + public long getCurrentDateInTimeMillis() { + return mDate.getTimeInMillis(); + }//实现函数——得到当前的秒数 + + /** + * Set the current date + * + * @param date The current date in millis + */ + public void setCurrentDate(long date) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(date); + setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), + cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); + } + + /** + * Set the current date + * + * @param year The current year + * @param month The current month + * @param dayOfMonth The current dayOfMonth + * @param hourOfDay The current hourOfDay + * @param minute The current minute + */ + public void setCurrentDate(int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + setCurrentYear(year); + setCurrentMonth(month); + setCurrentDay(dayOfMonth); + setCurrentHour(hourOfDay); + setCurrentMinute(minute); + } + + /** + * Get current year + * + * @return The current year + */ + public int getCurrentYear() { + return mDate.get(Calendar.YEAR); + } + + /** + * Set current year + * + * @param year The current year + */ + public void setCurrentYear(int year) { + if (!mInitialising && year == getCurrentYear()) { + return; + } + mDate.set(Calendar.YEAR, year); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current month in the year + * + * @return The current month in the year + */ + public int getCurrentMonth() { + return mDate.get(Calendar.MONTH); + } + + /** + * Set current month in the year + * + * @param month The month in the year + */ + public void setCurrentMonth(int month) { + if (!mInitialising && month == getCurrentMonth()) { + return; + } + mDate.set(Calendar.MONTH, month); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current day of the month + * + * @return The day of the month + */ + public int getCurrentDay() { + return mDate.get(Calendar.DAY_OF_MONTH); + } + + /** + * Set current day of the month + * + * @param dayOfMonth The day of the month + */ + public void setCurrentDay(int dayOfMonth) { + if (!mInitialising && dayOfMonth == getCurrentDay()) { + return; + } + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current hour in 24 hour mode, in the range (0~23) + * @return The current hour in 24 hour mode + */ + public int getCurrentHourOfDay() { + return mDate.get(Calendar.HOUR_OF_DAY); + } + + private int getCurrentHour() { + if (mIs24HourView){ + return getCurrentHourOfDay(); + } else { + int hour = getCurrentHourOfDay(); + if (hour > HOURS_IN_HALF_DAY) { + return hour - HOURS_IN_HALF_DAY; + } else { + return hour == 0 ? HOURS_IN_HALF_DAY : hour; + } + } + } + + /** + * Set current hour in 24 hour mode, in the range (0~23) + * + * @param hourOfDay + */ + public void setCurrentHour(int hourOfDay) { + if (!mInitialising && hourOfDay == getCurrentHourOfDay()) { + return; + } + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + if (!mIs24HourView) { + if (hourOfDay >= HOURS_IN_HALF_DAY) { + mIsAm = false; + if (hourOfDay > HOURS_IN_HALF_DAY) { + hourOfDay -= HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true; + if (hourOfDay == 0) { + hourOfDay = HOURS_IN_HALF_DAY; + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(hourOfDay); + onDateTimeChanged(); + } + + /** + * Get currentMinute + * + * @return The Current Minute + */ + public int getCurrentMinute() { + return mDate.get(Calendar.MINUTE); + } + + /** + * Set current minute + */ + public void setCurrentMinute(int minute) { + if (!mInitialising && minute == getCurrentMinute()) { + return; + } + mMinuteSpinner.setValue(minute); + mDate.set(Calendar.MINUTE, minute); + onDateTimeChanged(); + } + + /** + * @return true if this is in 24 hour view else false. + */ + public boolean is24HourView () { + return mIs24HourView; + } + + /** + * Set whether in 24 hour or AM/PM mode. + * + * @param is24HourView True for 24 hour mode. False for AM/PM mode. + */ + public void set24HourView(boolean is24HourView) { + if (mIs24HourView == is24HourView) { + return; + } + mIs24HourView = is24HourView; + mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE); + int hour = getCurrentHourOfDay(); + updateHourControl(); + setCurrentHour(hour); + updateAmPmControl(); + } + /** + * 几个辅助方法,用于更新日期、上午/下午选择和小时选择控件的显示和属性 + * 这些方法的作用是在选择器控件显示之前或用户改变了日期、时间模式时,更新相应控件的显示和属性,以保持界面的正确性和一致性 + */ + private void updateDateControl() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1); + mDateSpinner.setDisplayedValues(null); + for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) { + cal.add(Calendar.DAY_OF_YEAR, 1); + mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); + } + mDateSpinner.setDisplayedValues(mDateDisplayValues); + mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); + mDateSpinner.invalidate(); + } + + private void updateAmPmControl() { + if (mIs24HourView) { + mAmPmSpinner.setVisibility(View.GONE); + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM; + mAmPmSpinner.setValue(index); + mAmPmSpinner.setVisibility(View.VISIBLE); + } + } + + private void updateHourControl() { + if (mIs24HourView) { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); + } else { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); + } + } + + /** + * Set the callback that indicates the 'Set' button has been pressed. + * @param callback the callback, if null will do nothing + */ + public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { + mOnDateTimeChangedListener = callback; + } + + private void onDateTimeChanged() { + if (mOnDateTimeChangedListener != null) { + mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), + getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); + } + } +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java new file mode 100644 index 0000000..52640a8 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java @@ -0,0 +1,126 @@ +package net.micode.notes.ui; + +import java.util.Calendar; + +import net.micode.notes.R; +import net.micode.notes.ui.DateTimePicker; +import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.text.format.DateFormat; +import android.text.format.DateUtils; +/** + * @Package: net.micode.notes.ui + * @ClassName: DateTimePickerDialog + * @Description: + * DateTimePickerDialog是一个自定义对话框,允许用户选择日期和时间。 + * 它继承自AlertDialog类,并实现OnClickListener接口。 + * 对话框包含一个DateTimePicker控件,用于选择日期和时间。 + * 通过OnDateTimeSetListener接口将选择的日期和时间传递给监听器。 + * 对话框还提供了设置24小时制和使用选择的日期更新对话框标题的方法。 + * onClick方法处理按钮点击事件,并在日期和时间设置完成时通知监听器。 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:32 AM + * @Version: 1.0 + */ +public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + + private Calendar mDate = Calendar.getInstance(); + private boolean mIs24HourView; + private OnDateTimeSetListener mOnDateTimeSetListener; + private DateTimePicker mDateTimePicker; + + /** + * 用于接收用户设置的日期和时间的接口。 + */ + public interface OnDateTimeSetListener { + void OnDateTimeSet(AlertDialog dialog, long date); + } + + /** + * @method DateTimePickerDialog + * @description + * 构造一个新的DateTimePickerDialog + * Remind me功能的对话框 + * @date: 12/21/2023 8:01 AM + * @author: YangYizhe + * @param context 上下文环境。 + * @param date 要在对话框中显示的初始日期。 + */ + public DateTimePickerDialog(Context context, long date) { + super(context); + mDateTimePicker = new DateTimePicker(context); + setView(mDateTimePicker); + + mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { + public void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + mDate.set(Calendar.YEAR, year); + mDate.set(Calendar.MONTH, month); + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + mDate.set(Calendar.MINUTE, minute); + updateTitle(mDate.getTimeInMillis()); + } + }); + + mDate.setTimeInMillis(date); + mDate.set(Calendar.SECOND, 0); + mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); + + setButton(context.getString(R.string.datetime_dialog_ok), this); + setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener) null); + + set24HourView(DateFormat.is24HourFormat(this.getContext())); + updateTitle(mDate.getTimeInMillis()); + } + + /** + * 设置对话框是否为24小时制。 + * + * @param is24HourView 如果对话框为24小时制,则为true;否则为false。 + */ + public void set24HourView(boolean is24HourView) { + mIs24HourView = is24HourView; + } + + /** + * 设置日期和时间设置监听器。 + * + * @param callBack 要通知的监听器。 + */ + public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { + mOnDateTimeSetListener = callBack; + } + + /** + * 使用指定的日期更新对话框标题。 + * + * @param date 要显示在标题中的日期。 + */ + private void updateTitle(long date) { + int flag = + DateUtils.FORMAT_SHOW_YEAR | + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; + flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; + + setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); + } + + /** + * 处理按钮点击事件。 + * + * @param arg0 接收到点击事件的对话框。 + * @param arg1 被点击的按钮。 + */ + public void onClick(DialogInterface arg0, int arg1) { + if (mOnDateTimeSetListener != null) { + mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); + } + } + +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java b/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java new file mode 100644 index 0000000..b437d41 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/DropdownMenu.java @@ -0,0 +1,62 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.PopupMenu; +import android.widget.PopupMenu.OnMenuItemClickListener; + +import net.micode.notes.R; +/** + * @Package: net.micode.notes.ui + * @ClassName: DropdownMenu + * @Description: + * DropdownMenu是一个自定义下拉菜单控件。 + * 它使用Button作为触发器,通过PopupMenu显示菜单选项。 + * 构造函数接收一个上下文环境、一个Button和菜单资源的ID。 + * 通过setOnDropdownMenuItemClickListener方法设置菜单选项的点击监听器。 + * 可以通过findItem方法查找特定的菜单选项。 + * 通过setTitle方法设置下拉菜单的标题 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:36 AM + * @Version: 1.0 + */ +public class DropdownMenu { + private Button mButton; + private PopupMenu mPopupMenu; + //声明一个下拉菜单 + private Menu mMenu; + + public DropdownMenu(Context context, Button button, int menuId) { + mButton = button; + mButton.setBackgroundResource(R.drawable.dropdown_icon); + //设置这个view的背景 + mPopupMenu = new PopupMenu(context, mButton); + mMenu = mPopupMenu.getMenu(); + mPopupMenu.getMenuInflater().inflate(menuId, mMenu); + //MenuInflater是用来实例化Menu目录下的Menu布局文件 + //根据ID来确认menu的内容选项 + mButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPopupMenu.show(); + } + }); + } + + public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { + if (mPopupMenu != null) { + mPopupMenu.setOnMenuItemClickListener(listener); + } + } + + public MenuItem findItem(int id) { + return mMenu.findItem(id); + }//对于菜单选项的初始化,根据索引搜索菜单需要的选项 + + public void setTitle(CharSequence title) { + mButton.setText(title); + }//布局文件,设置标题 +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java new file mode 100644 index 0000000..8c3a217 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/FoldersListAdapter.java @@ -0,0 +1,83 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.database.Cursor; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; + +/** + * @Package: net.micode.notes.ui + * @ClassName: FoldersListAdapter + * @Description: + * FoldersListAdapter是一个用于展示便签文件夹的列表适配器。 + * 它继承了CursorAdapter类,主要负责便签数据库和用户界面的交互。 + * 通过PROJECTION数组定义了需要从数据库中获取的数据列。 + * 它通过newView方法创建文件夹视图,并通过bindView方法将布局文件和数据绑定在一起。 + * getFolderName方法可以根据位置获取对应便签文件夹的名称 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:37 AM + * @Version: 1.0 + */ +public class FoldersListAdapter extends CursorAdapter { + //CursorAdapter是Cursor和ListView的接口 + //FoldersListAdapter继承了CursorAdapter的类 + //主要作用是便签数据库和用户的交互 + //这里就是用folder(文件夹)的形式展现给用户 + public static final String [] PROJECTION = { + NoteColumns.ID, + NoteColumns.SNIPPET + };//调用数据库中便签的ID和片段 + + public static final int ID_COLUMN = 0; + public static final int NAME_COLUMN = 1; + + public FoldersListAdapter(Context context, Cursor c) { + super(context, c); + // TODO Auto-generated constructor stub + }//数据库操作 + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + //ViewGroup是容器 + return new FolderListItem(context); + }//创建一个文件夹,对于各文件夹中子标签的初始化 + + @Override + public void bindView(View view, Context context, Cursor cursor) { + if (view instanceof FolderListItem) { + String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + ((FolderListItem) view).bind(folderName); + } + }//将各个布局文件绑定起来 + + public String getFolderName(Context context, int position) { + Cursor cursor = (Cursor) getItem(position); + return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + }//根据数据库中标签的ID得到标签的各项内容 + + private class FolderListItem extends LinearLayout { + private TextView mName; + + public FolderListItem(Context context) { + super(context); + //操作数据库 + inflate(context, R.layout.folder_list_item, this); + //根据布局文件的名字等信息将其找出来 + mName = (TextView) findViewById(R.id.tv_folder_name); + } + + public void bind(String name) { + mName.setText(name); + } + } + +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java new file mode 100644 index 0000000..c935358 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NoteEditText.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.Context; +import android.graphics.Rect; +import android.text.Layout; +import android.text.Selection; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.URLSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.view.ContextMenu; +import android.view.KeyEvent; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.widget.EditText; + +import net.micode.notes.R; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Package: net.micode.notes.ui + * @ClassName: NoteEditText + * @Description: + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:38 AM + * @Version: 1.0 + */ +public class NoteEditText extends EditText { + //常量标识 + private static final String TAG = "NoteEditText"; + //声明整型变量,文本索引 + private int mIndex; + //声明整型变量 + private int mSelectionStartBeforeDelete; + + //声明字符串常量,标志电话、网址、邮件 + private static final String SCHEME_TEL = "tel:" ; + private static final String SCHEME_HTTP = "http:" ; + private static final String SCHEME_EMAIL = "mailto:" ; + + //设置映射,将文本内容(电话、网址、邮件)做链接处理 + private static final Map sSchemaActionResMap = new HashMap(); + static { + sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); + sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web); + sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email); + } + + /** + * Call by the {@link NoteEditActivity} to delete or add edit text + * 该接口用于实现对TextView组件中的文字信息进行修改 + */ + public interface OnTextViewChangeListener { + /** + * Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens + * and the text is null + * 当delete键按下时删除当前编辑的文字块 + */ + void onEditTextDelete(int index, String text); + + /** + * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} + * happen + * 当enter键按下时添加一个文字编辑块 + */ + void onEditTextEnter(int index, String text); + + /** + * Hide or show item option when text change + * 当文字发生变化时隐藏或者显示设置 + */ + void onTextChange(int index, boolean hasText); + } + + //声明文本视图变化监听器 + private OnTextViewChangeListener mOnTextViewChangeListener; + + /** + * 构造方法,实例化NoteEditText + */ + public NoteEditText(Context context) { + super(context, null); + mIndex = 0; + } + + //设置索引号 + public void setIndex(int index) { + mIndex = index; + } + + /** + * 设置文本视图变化监听器 + */ + public void setOnTextViewChangeListener(OnTextViewChangeListener listener) { + mOnTextViewChangeListener = listener; + } + + /** + * 构造方法,是由参数集(文本编辑风格)实例化NoteEditText + */ + public NoteEditText(Context context, AttributeSet attrs) { + super(context, attrs, android.R.attr.editTextStyle); + } + /** + * 构造方法,是由参数集(文本编辑风格、定义风格)实例化NoteEditText + */ + public NoteEditText(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + // TODO Auto-generated constructor stub + } + + /** + * @method onTouchEvent + * @description 处理触摸事件,根据触摸点的位置设置光标的位置 + * @date: 12/21/2023 12:41 AM + * @author: YangYizhe + * @param + * @return + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + + int x = (int) event.getX(); + int y = (int) event.getY(); + x -= getTotalPaddingLeft(); + y -= getTotalPaddingTop(); + x += getScrollX(); + y += getScrollY(); + Layout layout = getLayout(); + int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); + Selection.setSelection(getText(), off); + break; + } + return super.onTouchEvent(event); + } + /** + * @method onKeyDown + * @description 监听键盘按键按下 + * @date: 12/21/2023 12:40 AM + * @author: YangYizhe + * @param keyCode 键盘按键的编码 + * @param event 按键事件 + * @return boolean + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_ENTER: + if (mOnTextViewChangeListener != null) { + return false; + } + break; + case KeyEvent.KEYCODE_DEL: + mSelectionStartBeforeDelete = getSelectionStart(); + break; + default: + break; + } + return super.onKeyDown(keyCode, event); + } + + /** + * @method onKeyUp + * @description 监听按键抬起 + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param keyCode + * @param event + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch(keyCode) { + case KeyEvent.KEYCODE_DEL: + if (mOnTextViewChangeListener != null) { + if (0 == mSelectionStartBeforeDelete && mIndex != 0) { + mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString()); + return true; + } + } else { + Log.d(TAG, "OnTextViewChangeListener was not seted"); + } + break; + case KeyEvent.KEYCODE_ENTER: + if (mOnTextViewChangeListener != null) { + int selectionStart = getSelectionStart(); + String text = getText().subSequence(selectionStart, length()).toString(); + setText(getText().subSequence(0, selectionStart)); + mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text); + } else { + Log.d(TAG, "OnTextViewChangeListener was not seted"); + } + break; + default: + break; + } + return super.onKeyUp(keyCode, event); + } + + /** + * @method onFocusChanged + * @description 处理当前视图下的焦点改变事件 + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param focused 代表获得或失去焦点 + * @param direction + * @param previouslyFocusedRect 上一个访问的焦点区域 + */ + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + if (mOnTextViewChangeListener != null) { + if (!focused && TextUtils.isEmpty(getText())) { + mOnTextViewChangeListener.onTextChange(mIndex, false); + } else { + mOnTextViewChangeListener.onTextChange(mIndex, true); + } + } + super.onFocusChanged(focused, direction, previouslyFocusedRect); + } + + /** + * @method onCreateContextMenu + * @description + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param + * @return + */ + @Override + protected void onCreateContextMenu(ContextMenu menu) { + if (getText() instanceof Spanned) { + int selStart = getSelectionStart(); + int selEnd = getSelectionEnd(); + + int min = Math.min(selStart, selEnd); + int max = Math.max(selStart, selEnd); + + final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); + if (urls.length == 1) { + int defaultResId = 0; + for(String schema: sSchemaActionResMap.keySet()) { + if(urls[0].getURL().indexOf(schema) >= 0) { + defaultResId = sSchemaActionResMap.get(schema); + break; + } + } + + if (defaultResId == 0) { + defaultResId = R.string.note_link_other; + } + menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( + new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // goto a new intent + urls[0].onClick(NoteEditText.this); + return true; + } + }); + } + } + super.onCreateContextMenu(menu); + } +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java new file mode 100644 index 0000000..2b0e901 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -0,0 +1,1103 @@ +package net.micode.notes.ui; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.appwidget.AppWidgetManager; +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.ActionMode; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Display; +import android.view.HapticFeedbackConstants; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnCreateContextMenuListener; +import android.view.View.OnTouchListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.PopupMenu; +import android.widget.TextView; +import android.widget.Toast; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.remote.GTaskSyncService; +import net.micode.notes.model.WorkingNote; +import net.micode.notes.tool.BackupUtils; +import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; +import net.micode.notes.widget.NoteWidgetProvider_2x; +import net.micode.notes.widget.NoteWidgetProvider_4x; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashSet; +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesListActivity + * @Description: + * 小米便签的主入口,提供了一系列便签操作主要功能 + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/20 23:02 + * @Version: 1.0 + */ +public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener { + + private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; + + private static final int FOLDER_LIST_QUERY_TOKEN = 1; + + private static final int MENU_FOLDER_DELETE = 0; + + private static final int MENU_FOLDER_VIEW = 1; + + private static final int MENU_FOLDER_CHANGE_NAME = 2; + + private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; + + private enum ListEditState { + NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER + }; + + private ListEditState mState; + + private BackgroundQueryHandler mBackgroundQueryHandler; + + private NotesListAdapter mNotesListAdapter; + + private ListView mNotesListView; + + private Button mAddNewNote; + + private boolean mDispatch; + + private int mOriginY; + + private int mDispatchY; + + private TextView mTitleBar; + + private long mCurrentFolderId; + + private ContentResolver mContentResolver; + + private ModeCallback mModeCallBack; + + private static final String TAG = "NotesListActivity"; + + public static final int NOTES_LISTVIEW_SCROLL_RATE = 30; + + private NoteItemData mFocusNoteDataItem; + + private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?"; + + private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR (" + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + + NoteColumns.NOTES_COUNT + ">0)"; + + private final static int REQUEST_CODE_OPEN_NODE = 102; + private final static int REQUEST_CODE_NEW_NODE = 103; + @Override + /** + * @method onCreate + * @description: + * @date: 2023/12/21 1:52 + * @author: WUSHUXIAN + * @param void + * @return void + */ + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); // 调用父类的onCreate函数 + setContentView(R.layout.note_list); + initResources(); + setAppInfoFromRawRes(); + } + + @Override + /** + * @method onActivityResult + * @description: + * 参数: + * requestCode: + * resultCode: + * data; + * @date: 2023/12/20 23:26 + * @author: WUSHUXIAN + * @param void + * @return void + */ + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK + && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) { + mNotesListAdapter.changeCursor(null); + } else { + super.onActivityResult(requestCode, resultCode, data);// 调用 Activity 的onActivityResult() + } + } + /** + * @method setAppInfoFromRawRes + * @description: + * @date: 2023/12/20 23:24 + * @author: WUSHUXIAN + * @param + * @return + */ + private void setAppInfoFromRawRes() { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);// Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。 + if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) { + StringBuilder sb = new StringBuilder(); + InputStream in = null; + try { + in = getResources().openRawResource(R.raw.introduction); + if (in != null) { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + char [] buf = new char[1024]; + int len = 0; + while ((len = br.read(buf)) > 0) { + sb.append(buf, 0, len); + } + } else { + Log.e(TAG, "Read introduction file error"); + return; + } + } catch (IOException e) { + e.printStackTrace(); + return; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + // 创建空的WorkingNote + WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER, + AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE, + ResourceParser.RED); + note.setWorkingText(sb.toString()); + if (note.saveNote()) { + // 更新保存note的信息 + sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); + } else { + Log.e(TAG, "Save introduction note error"); + return; + } + } + } + + @Override + protected void onStart() { + super.onStart(); + startAsyncNotesListQuery(); + } + /** + * @method initResources + * @description 初始化资源 + * @date: 2023/12/20 23:09 + * @author: WUSHUXIAN + * @param + * @return + */ + private void initResources() { + mContentResolver = this.getContentResolver(); // 获取应用程序的数据,得到类似数据表的东西 + mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver()); + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + + // findViewById 是安卓编程的定位函数,主要是引用.R文件里的引用名 + mNotesListView = (ListView) findViewById(R.id.notes_list); // 绑定XML中的ListView,作为Item的容器 + mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null), + null, false); + mNotesListView.setOnItemClickListener(new OnListItemClickListener()); + mNotesListView.setOnItemLongClickListener(this); + mNotesListAdapter = new NotesListAdapter(this); + mNotesListView.setAdapter(mNotesListAdapter); + mAddNewNote = (Button) findViewById(R.id.btn_new_note);// 在activity中要获取该按钮 + mAddNewNote.setOnClickListener(this); + mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener()); + mDispatch = false; + mDispatchY = 0; + mOriginY = 0; + mTitleBar = (TextView) findViewById(R.id.tv_title_bar); + mState = ListEditState.NOTE_LIST; + mModeCallBack = new ModeCallback(); + } + + // + /** + * @Package: net.micode.notes.ui + * @ClassName: ModeCallback + * @Description: 继承自ListView.MultiChoiceModeListener 和 OnMenuItemClickListener + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/20 23:37 + * @Version: 1.0 + */ + private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener { + private DropdownMenu mDropDownMenu; + private ActionMode mActionMode; + private MenuItem mMoveMenu; + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + getMenuInflater().inflate(R.menu.note_list_options, menu); + menu.findItem(R.id.delete).setOnMenuItemClickListener(this); + mMoveMenu = menu.findItem(R.id.move); + if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER + || DataUtils.getUserFolderCount(mContentResolver) == 0) { + mMoveMenu.setVisible(false); + } else { + mMoveMenu.setVisible(true); + mMoveMenu.setOnMenuItemClickListener(this); + } + mActionMode = mode; + mNotesListAdapter.setChoiceMode(true); + mNotesListView.setLongClickable(false); + mAddNewNote.setVisibility(View.GONE); + + View customView = LayoutInflater.from(NotesListActivity.this).inflate( + R.layout.note_list_dropdown_menu, null); + mode.setCustomView(customView); + mDropDownMenu = new DropdownMenu(NotesListActivity.this, + (Button) customView.findViewById(R.id.selection_menu), + R.menu.note_list_dropdown); + mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){ + public boolean onMenuItemClick(final MenuItem item) { + mNotesListAdapter.selectAll(!mNotesListAdapter.isAllSelected()); + updateMenu(); + return true; + } + + }); + return true; + } + /** + * @method updateMenu + * @description 更新菜单 + * @date: 2023/12/16 23:36 + * @author: WUSHUXIAN + * @param + * @return + */ + private void updateMenu() { + int selectedCount = mNotesListAdapter.getSelectedCount(); + // Update dropdown menu + String format = getResources().getString(R.string.menu_select_title, selectedCount); + mDropDownMenu.setTitle(format); // 更改标题 + MenuItem item = mDropDownMenu.findItem(R.id.action_select_all); + if (item != null) { + if (mNotesListAdapter.isAllSelected()) { + item.setChecked(true); + item.setTitle(R.string.menu_deselect_all); + } else { + item.setChecked(false); + item.setTitle(R.string.menu_select_all); + } + } + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + // TODO Auto-generated method stub + return false; + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + // TODO Auto-generated method stub + return false; + } + + public void onDestroyActionMode(ActionMode mode) { + mNotesListAdapter.setChoiceMode(false); + mNotesListView.setLongClickable(true); + mAddNewNote.setVisibility(View.VISIBLE); + } + + public void finishActionMode() { + mActionMode.finish(); + } + + public void onItemCheckedStateChanged(ActionMode mode, int position, long id, + boolean checked) { + mNotesListAdapter.setCheckedItem(position, checked); + updateMenu(); + } + /** + * @method onMenuItemClick + * @description: + * @date: 2023/12/20 23:39 + * @author: WUSHUXIAN + * @param + * @return + */ + public boolean onMenuItemClick(MenuItem item) { + if (mNotesListAdapter.getSelectedCount() == 0) { + Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none), + Toast.LENGTH_SHORT).show(); + return true; + } + + int itemId = item.getItemId(); + if (itemId == R.id.delete) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_notes, + mNotesListAdapter.getSelectedCount())); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + batchDelete(); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + } else if (itemId == R.id.move) { + startQueryDestinationFolders(); + } else { + return false; + } + return true; + } + } + //接口的实现 + private class NewNoteOnTouchListener implements OnTouchListener { + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + Display display = getWindowManager().getDefaultDisplay(); + int screenHeight = display.getHeight(); + int newNoteViewHeight = mAddNewNote.getHeight(); + int start = screenHeight - newNoteViewHeight; + int eventY = start + (int) event.getY(); + /** + * Minus TitleBar's height + */ + if (mState == ListEditState.SUB_FOLDER) { + eventY -= mTitleBar.getHeight(); + start -= mTitleBar.getHeight(); + } + /** + * HACKME:When click the transparent part of "New Note" button, dispatch + * the event to the list view behind this button. The transparent part of + * "New Note" button could be expressed by formula y=-0.12x+94锛圲nit:pixel锛� + * and the line top of the button. The coordinate based on left of the "New + * Note" button. The 94 represents maximum height of the transparent part. + * Notice that, if the background of the button changes, the formula should + * also change. This is very bad, just for the UI designer's strong requirement. + */ + if (event.getY() < (event.getX() * (-0.12) + 94)) { + View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1 + - mNotesListView.getFooterViewsCount()); + if (view != null && view.getBottom() > start + && (view.getTop() < (start + 94))) { + mOriginY = (int) event.getY(); + mDispatchY = eventY; + event.setLocation(event.getX(), mDispatchY); + mDispatch = true; + return mNotesListView.dispatchTouchEvent(event); + } + } + break; + } + case MotionEvent.ACTION_MOVE: { + if (mDispatch) { + mDispatchY += (int) event.getY() - mOriginY; + event.setLocation(event.getX(), mDispatchY); + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + default: { + if (mDispatch) { + event.setLocation(event.getX(), mDispatchY); + mDispatch = false; + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + } + return false; + } + + }; + /** + * @method startAsyncNotesListQuery + * @description: 启动异步Notes列表查询 + * @date: 2023/12/20 23:45 + * @author: WUSHUXIAN + * @param + * @return + */ + private void startAsyncNotesListQuery() { + String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION : NORMAL_SELECTION; + mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null, + Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {String.valueOf(mCurrentFolderId)}, + NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC"); + } + /** + * @Package: net.micode.notes.ui + * @ClassName: BackgroundQueryHandler + * @Description: 对AsyncQueryHandler的拓展,背景查询处理 + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/21 0:01 + * @Version: 1.0 + */ + private final class BackgroundQueryHandler extends AsyncQueryHandler { + public BackgroundQueryHandler(ContentResolver contentResolver) { + super(contentResolver); + } + + @Override + /** + * @method onQueryComplete + * @description: 在异步查询完成时调用。 + * @date: 2023/12/20 23:56 + * @author: WUSHUXIAN + * @param token 标识查询的令牌 + * @param cookie 传入的cookie对象 + * @param cursor 保存查询结果的光标 + * @return void + */ + protected void onQueryComplete(int token, Object cookie, Cursor cursor) { + switch (token) { + case FOLDER_NOTE_LIST_QUERY_TOKEN: + mNotesListAdapter.changeCursor(cursor); + break; + case FOLDER_LIST_QUERY_TOKEN: + if (cursor != null && cursor.getCount() > 0) { + showFolderListMenu(cursor); + } else { + Log.e(TAG, "Query folder failed"); + } + break; + default: + return; + } + } + } + + private void showFolderListMenu(Cursor cursor) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(R.string.menu_title_select_folder); + final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + DataUtils.batchMoveToFolder(mContentResolver, + mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which)); + Toast.makeText( + NotesListActivity.this, + getString(R.string.format_move_notes_to_folder, + mNotesListAdapter.getSelectedCount(), + adapter.getFolderName(NotesListActivity.this, which)), + Toast.LENGTH_SHORT).show(); + mModeCallBack.finishActionMode(); + } + }); + builder.show(); + } + /** + * @method createNewNote + * @description 创建便签 + * @date: 12/21/2023 1:58 AM + * @author: YangYizhe + * @param + * @return + */ + private void createNewNote() { + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId); + this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE); + } + /** + * @method batchDelete + * @description: + * 删除便签操作 + * @date: 2023/12/21 0:14 + * @author: WUSHUXIAN + * @param + * @return void + */ + @SuppressLint("StaticFieldLeak") + private void batchDelete() { + new AsyncTask>() { + protected HashSet doInBackground(Void... unused) { + HashSet widgets = mNotesListAdapter.getSelectedWidget(); + //如果没有同步,直接删除 + if (!isSyncMode()) { + if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter + .getSelectedItemIds())) { + } else { + Log.e(TAG, "Delete notes error, should not happens"); + } + } + //已同步,将删除的便签移到垃圾桶 + else { + if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter + .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) { + Log.e(TAG, "Move notes to trash folder error, should not happens"); + } + } + return widgets; + } + + @Override + protected void onPostExecute(HashSet widgets) { + if (widgets != null) { + for (AppWidgetAttribute widget : widgets) { + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + mModeCallBack.finishActionMode(); + } + }.execute(); + } + /** + * @method deleteFolder + * @description: 删除文件夹 + * @date: 2023/12/21 0:32 + * @author: WUSHUXIAN + * @param folderId 文件标识 + * @return void + */ + private void deleteFolder(long folderId) { + if (folderId == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Wrong folder id, should not happen " + folderId); + return; + } + + HashSet ids = new HashSet(); + ids.add(folderId); + HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, + folderId); + if (!isSyncMode()) { + // if not synced, delete folder directly + DataUtils.batchDeleteNotes(mContentResolver, ids); + } else { + // in sync mode, we'll move the deleted folder into the trash folder + DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER); + } + if (widgets != null) { + for (AppWidgetAttribute widget : widgets) { + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + } + + /** + * @method openNode + * @description + * 打开便签的功能 + * @date: 12/21/2023 8:05 AM + * @author: YangYizhe + * @param data + */ + private void openNode(NoteItemData data) { + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, data.getId()); + this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + } + /** + * @method openFolder + * @description 打开文件夹功能 + * @date: 12/21/2023 8:05 AM + * @author: YangYizhe + * @param data + */ + private void openFolder(NoteItemData data) { + mCurrentFolderId = data.getId(); + startAsyncNotesListQuery(); + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mState = ListEditState.CALL_RECORD_FOLDER; + mAddNewNote.setVisibility(View.GONE); + } else { + mState = ListEditState.SUB_FOLDER; + } + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mTitleBar.setText(R.string.call_record_folder_name); + } else { + mTitleBar.setText(data.getSnippet()); + } + mTitleBar.setVisibility(View.VISIBLE); + } + /** + * @method onClick + * @description 如果碰到写便签按钮,新建便签 + * @date: 12/21/2023 8:06 AM + * @author: YangYizhe + * @param + */ + public void onClick(View v) { + if (v.getId() == R.id.btn_new_note) { + createNewNote(); + } + } + + private void showSoftInput() { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + private void hideSoftInput(View view) { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + /** + * @method showCreateOrModifyFolderDialog + * @description: 创建或者修改文件夹时显示对话框 + * @date: 2023/12/21 0:39 + * @author: WUSHUXIAN + * @param create + * @return void + */ + private void showCreateOrModifyFolderDialog(final boolean create) { + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null); + final EditText etName = (EditText) view.findViewById(R.id.et_foler_name); + showSoftInput(); + if (!create) { + if (mFocusNoteDataItem != null) { + etName.setText(mFocusNoteDataItem.getSnippet()); + builder.setTitle(getString(R.string.menu_folder_change_name)); + } else { + Log.e(TAG, "The long click data item is null"); + return; + } + } else { + etName.setText(""); + builder.setTitle(this.getString(R.string.menu_create_folder)); + } + + builder.setPositiveButton(android.R.string.ok, null); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + hideSoftInput(etName); + } + }); + + final Dialog dialog = builder.setView(view).show(); + final Button positive = (Button)dialog.findViewById(android.R.id.button1); + positive.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + hideSoftInput(etName); + String name = etName.getText().toString(); + if (DataUtils.checkVisibleFolderName(mContentResolver, name)) { + Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name), + Toast.LENGTH_LONG).show(); + etName.setSelection(0, etName.length()); + return; + } + if (!create) { + if (!TextUtils.isEmpty(name)) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID + + "=?", new String[] { + String.valueOf(mFocusNoteDataItem.getId()) + }); + } + } else if (!TextUtils.isEmpty(name)) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + mContentResolver.insert(Notes.CONTENT_NOTE_URI, values); + } + dialog.dismiss(); + } + }); + //如果便签名是空的,则禁用确认按钮 + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } + etName.addTextChangedListener(new TextWatcher() { + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // TODO Auto-generated method stub + + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } else { + positive.setEnabled(true); + } + } + + public void afterTextChanged(Editable s) { + // TODO Auto-generated method stub + + } + }); + } + + /* (non-Javadoc) + * @see android.app.Activity#onBackPressed() + * 按返回键时根据情况更改类中的数据 + */ + @Override + public void onBackPressed() { + switch (mState) { + case SUB_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + startAsyncNotesListQuery(); + mTitleBar.setVisibility(View.GONE); + break; + case CALL_RECORD_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + mAddNewNote.setVisibility(View.VISIBLE); + mTitleBar.setVisibility(View.GONE); + startAsyncNotesListQuery(); + break; + case NOTE_LIST: + super.onBackPressed(); + break; + default: + break; + } + } + + /** + * @param appWidgetId + * @param appWidgetType + * 根据不同类型的widget更新插件,通过intent传送数据 + */ + private void updateWidget(int appWidgetId, int appWidgetType) { + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + if (appWidgetType == Notes.TYPE_WIDGET_2X) { + intent.setClass(this, NoteWidgetProvider_2x.class); + } else if (appWidgetType == Notes.TYPE_WIDGET_4X) { + intent.setClass(this, NoteWidgetProvider_4x.class); + } else { + Log.e(TAG, "Unspported widget type"); + return; + } + + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { + appWidgetId + }); + + sendBroadcast(intent); + setResult(RESULT_OK, intent); + } + /** + * @method OnCreateContextMenuListener + * @description: 生成便签初始界面 + * @date: 2023/12/21 1:16 + * @author: WUSHUXIAN + */ + private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() { + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + if (mFocusNoteDataItem != null) { + menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); + menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view); + menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); + menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name); + } + } + }; + + @Override + public void onContextMenuClosed(Menu menu) { + if (mNotesListView != null) { + mNotesListView.setOnCreateContextMenuListener(null); + } + super.onContextMenuClosed(menu); + } + + /* (non-Javadoc) + * @see android.app.Activity#onContextItemSelected(android.view.MenuItem) + * 针对menu中不同的选择进行不同的处理,里面详细注释 + */ + @Override + public boolean onContextItemSelected(MenuItem item) { + if (mFocusNoteDataItem == null) { + Log.e(TAG, "The long click data item is null"); + return false; + } + switch (item.getItemId()) { + case MENU_FOLDER_VIEW: + openFolder(mFocusNoteDataItem);//打开对应文件 + break; + case MENU_FOLDER_DELETE: + AlertDialog.Builder builder = new AlertDialog.Builder(this);//设置确认是否删除的对话框 + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_folder)); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + deleteFolder(mFocusNoteDataItem.getId()); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show();//显示对话框 + break; + case MENU_FOLDER_CHANGE_NAME: + showCreateOrModifyFolderDialog(false); + break; + default: + break; + } + + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.clear(); + if (mState == ListEditState.NOTE_LIST) { + getMenuInflater().inflate(R.menu.note_list, menu); + // set sync or sync_cancel + menu.findItem(R.id.menu_sync).setTitle( + GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync); + } else if (mState == ListEditState.SUB_FOLDER) { + getMenuInflater().inflate(R.menu.sub_folder, menu); + } else if (mState == ListEditState.CALL_RECORD_FOLDER) { + getMenuInflater().inflate(R.menu.call_record_folder, menu); + } else { + Log.e(TAG, "Wrong state:" + mState); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + if (itemId == R.id.menu_new_folder) { + showCreateOrModifyFolderDialog(true); + } else if (itemId == R.id.menu_export_text) { + exportNoteToText(); + } else if (itemId == R.id.menu_sync) { + if (isSyncMode()) { + if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) { + GTaskSyncService.startSync(this); + } else { + GTaskSyncService.cancelSync(this); + } + } else { + startPreferenceActivity(); + } + } else if (itemId == R.id.menu_setting) { + startPreferenceActivity(); + } else if (itemId == R.id.menu_new_note) { + createNewNote(); + } else if (itemId == R.id.menu_search) { + onSearchRequested(); + } + return true; + } + + /* (non-Javadoc) + * @see android.app.Activity#onSearchRequested() + * 直接调用startSearch函数 + */ + @Override + public boolean onSearchRequested() { + startSearch(null, false, null /* appData */, false); + return true; + } + + /** + * @method exportNoteToText + * @description 将便签导出,export text按钮 + * @date: 12/21/2023 8:08 AM + * @author: YangYizhe + */ + private void exportNoteToText() { + final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this); + new AsyncTask() { + + @Override + protected Integer doInBackground(Void... unused) { + return backup.exportToText(); + } + + @Override + protected void onPostExecute(Integer result) { + if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_unmounted)); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } else if (result == BackupUtils.STATE_SUCCESS) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.success_sdcard_export)); + builder.setMessage(NotesListActivity.this.getString( + R.string.format_exported_file_location, backup + .getExportedTextFileName(), backup.getExportedTextFileDir())); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } else if (result == BackupUtils.STATE_SYSTEM_ERROR) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_export)); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } + } + + }.execute(); + } + + + private boolean isSyncMode() { + return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; + } + + private void startPreferenceActivity() { + Activity from = getParent() != null ? getParent() : this; + Intent intent = new Intent(from, NotesPreferenceActivity.class); + from.startActivityIfNeeded(intent, -1); + } + + /** + * @Package: net.micode.notes.ui + * @ClassName: NotesListActivity + * @Description: 响应了按钮的点击 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 8:09 AM + * @Version: 1.0 + */ + private class OnListItemClickListener implements OnItemClickListener { + + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (view instanceof NotesListItem) { + NoteItemData item = ((NotesListItem) view).getItemData(); + if (mNotesListAdapter.isInChoiceMode()) { + if (item.getType() == Notes.TYPE_NOTE) { + position = position - mNotesListView.getHeaderViewsCount(); + mModeCallBack.onItemCheckedStateChanged(null, position, id, + !mNotesListAdapter.isSelectedItem(position)); + } + return; + } + + switch (mState) { + case NOTE_LIST: + if (item.getType() == Notes.TYPE_FOLDER + || item.getType() == Notes.TYPE_SYSTEM) { + openFolder(item); + } else if (item.getType() == Notes.TYPE_NOTE) { + openNode(item); + } else { + Log.e(TAG, "Wrong note type in NOTE_LIST"); + } + break; + case SUB_FOLDER: + case CALL_RECORD_FOLDER: + if (item.getType() == Notes.TYPE_NOTE) { + openNode(item); + } else { + Log.e(TAG, "Wrong note type in SUB_FOLDER"); + } + break; + default: + break; + } + } + } + + } + + /** + * 查询目标文件 + */ + private void startQueryDestinationFolders() { + String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?"; + selection = (mState == ListEditState.NOTE_LIST) ? selection: + "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")"; + + mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN, + null, + Notes.CONTENT_NOTE_URI, + FoldersListAdapter.PROJECTION, + selection, + new String[] { + String.valueOf(Notes.TYPE_FOLDER), + String.valueOf(Notes.ID_TRASH_FOLER), + String.valueOf(mCurrentFolderId) + }, + NoteColumns.MODIFIED_DATE + " DESC"); + } + + /** + * @method onItemLongClick + * @description + * 长按某一项时进行的操作 + * 如果长按的是便签,则通过ActionMode菜单实现;如果长按的是文件夹,则通过ContextMenu菜单实现; + * @date: 12/21/2023 8:10 AM + * @author: YangYizhe + * @param + * @return + */ + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + if (view instanceof NotesListItem) { + mFocusNoteDataItem = ((NotesListItem) view).getItemData(); + if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) { + if (mNotesListView.startActionMode(mModeCallBack) != null) { + mModeCallBack.onItemCheckedStateChanged(null, position, id, true); + mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } else { + Log.e(TAG, "startActionMode fails"); + } + } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) { + mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener); + } + } + return false; + } +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java new file mode 100644 index 0000000..d32a37b --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesListItem.java @@ -0,0 +1,123 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.text.format.DateUtils; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.ResourceParser.NoteItemBgResources; + + +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesListItem + * @Description: + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:35 PM + * @Version: 1.0 + */ +public class NotesListItem extends LinearLayout { + private ImageView mAlert;//闹钟图片 + private TextView mTitle; //标题 + private TextView mTime; //时间 + private TextView mCallName; // + private NoteItemData mItemData; //标签数据 + private CheckBox mCheckBox; //打钩框 + + /*初始化基本信息*/ + public NotesListItem(Context context) { + super(context); //super()它的主要作用是调整调用父类构造函数的顺序 + inflate(context, R.layout.note_item, this);//Inflate可用于将一个xml中定义的布局控件找出来,这里的xml是r。layout + //findViewById用于从contentView中查找指定ID的View,转换出来的形式根据需要而定; + mAlert = (ImageView) findViewById(R.id.iv_alert_icon); + mTitle = (TextView) findViewById(R.id.tv_title); + mTime = (TextView) findViewById(R.id.tv_time); + mCallName = (TextView) findViewById(R.id.tv_name); + mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); + } + ///根据data的属性对各个控件的属性的控制,主要是可见性Visibility,内容setText,格式setTextAppearance + public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { + if (choiceMode && data.getType() == Notes.TYPE_NOTE) { + mCheckBox.setVisibility(View.VISIBLE); ///设置可见行为可见 + mCheckBox.setChecked(checked); ///格子打钩 + } else { + mCheckBox.setVisibility(View.GONE); + } + + mItemData = data; + ///设置控件属性,一共三种情况,由data的id和父id是否与保存到文件夹的id一致来决定 + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mCallName.setVisibility(View.GONE); + mAlert.setVisibility(View.VISIBLE); + //设置该textview的style + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + //settext为设置内容 + mTitle.setText(context.getString(R.string.call_record_folder_name) + + context.getString(R.string.format_folder_files_count, data.getNotesCount())); + mAlert.setImageResource(R.drawable.call_record); + } else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { + mCallName.setVisibility(View.VISIBLE); + mCallName.setText(data.getCallName()); + mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem); + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + ///关于闹钟的设置 + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock);//图片来源的设置 + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } else { + mCallName.setVisibility(View.GONE); + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + ///设置title格式 + if (data.getType() == Notes.TYPE_FOLDER) { + mTitle.setText(data.getSnippet() + + context.getString(R.string.format_folder_files_count, + data.getNotesCount())); + mAlert.setVisibility(View.GONE); + } else { + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock);///设置图片来源 + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } + } + ///设置内容,获取相关时间,从data里编辑的日期中获取 + mTime. setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); + + setBackground(data); + } + //根据data的文件属性来设置背景 + private void setBackground(NoteItemData data) { + int id = data.getBgColorId(); + //,若是note型文件,则4种情况,对于4种不同情况的背景来源 + if (data.getType() == Notes.TYPE_NOTE) { + //单个数据并且只有一个子文件夹 + if (data.isSingle() || data.isOneFollowingFolder()) { + setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id)); + } else if (data.isLast()) {//是最后一个数据 + setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id)); + } else if (data.isFirst() || data.isMultiFollowingFolder()) {//是一个数据并有多个子文件夹 + setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id)); + } else { + setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id)); + } + } else { + //若不是note直接调用文件夹的背景来源 + setBackgroundResource(NoteItemBgResources.getFolderBgRes()); + } + } + public NoteItemData getItemData() { + return mItemData; + } +} \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java new file mode 100644 index 0000000..e4109c6 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java @@ -0,0 +1,492 @@ +package net.micode.notes.ui; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.ActionBar; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.remote.GTaskSyncService; + +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesPreferenceActivity + * @Description: + * NotesPreferenceActivity,在小米便签中主要实现的是对背景颜色和字体大小的数据储存。 + * 继承了PreferenceActivity主要功能为对系统信息和配置进行自动保存的Activity + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:42 PM + * @Version: 1.0 + */ +public class NotesPreferenceActivity extends PreferenceActivity { + public static final String PREFERENCE_NAME = "notes_preferences";//优先名 + public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";//同步账号 + public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";//同步时间 + public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; + private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";//同步密码 + private static final String AUTHORITIES_FILTER_KEY = "authorities"; + private PreferenceCategory mAccountCategory;//账户分组 + private GTaskReceiver mReceiver;//同步任务接收器 + private Account[] mOriAccounts;//账户 + private boolean mHasAddedAccount;//账户的hash标记 + + @Override + /** + * @method onCreate + * @description 创建一个activity,在函数里要完成所有的正常静态设置 + * @date: 12/23/2023 11:43 PM + * @author: YangYizhe + * @param [icicle] + * @return void + */ + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + /* using the app icon for navigation */ + getActionBar().setDisplayHomeAsUpEnabled(true);//给左上角图标的左边加上一个返回的图标 + addPreferencesFromResource(R.xml.preferences);//添加xml来源并显示 xml + mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);//根据同步账户关键码来初始化分组 + mReceiver = new GTaskReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); + registerReceiver(mReceiver, filter);//初始化同步组件 + mOriAccounts = null; + View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);//获取listvivew,ListView的作用:用于列出所有选择 + getListView().addHeaderView(header, null, true);//在listview组件上方添加其他组件 + } + + @Override + /** + * @method onResume + * @description activity交互功能的实现,用于接受用户的输入 + * @date: 12/23/2023 11:44 PM + * @author: YangYizhe + * @return void + */ + protected void onResume() { + super.onResume(); + + // need to set sync account automatically if user has added a new + // account + if (mHasAddedAccount) { + //若用户新加了账户则自动设置同步账户 + Account[] accounts = getGoogleAccounts();//获取google同步账户 + if (mOriAccounts != null && accounts.length > mOriAccounts.length) { + //若原账户不为空且当前账户有增加 + for (Account accountNew : accounts) { + boolean found = false; + for (Account accountOld : mOriAccounts) { + if (TextUtils.equals(accountOld.name, accountNew.name)) { + //更新账户 + found = true; + break; + } + } + if (!found) { + setSyncAccount(accountNew.name); + //若是没有找到旧的账户,那么同步账号中就只添加新账户 + break; + } + } + } + } + + refreshUI();//刷新标签界面 + } + + @Override + protected void onDestroy() { + if (mReceiver != null) { + unregisterReceiver(mReceiver);//注销接收器 + } + super.onDestroy();//执行父类的销毁动作 + } + + /** + * @method loadAccountPreference + * @description 重新设置账户信息 + * @date: 12/23/2023 11:45 PM + * @author: YangYizhe + * @param + * @return + */ + private void loadAccountPreference() { + mAccountCategory.removeAll();//销毁所有的分组 + Preference accountPref = new Preference(this);//建立首选项 + final String defaultAccount = getSyncAccountName(this); + accountPref.setTitle(getString(R.string.preferences_account_title)); + accountPref.setSummary(getString(R.string.preferences_account_summary));//设置首选项的大标题和小标题 + accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + //建立监听器 + if (!GTaskSyncService.isSyncing()) { + if (TextUtils.isEmpty(defaultAccount)) { + // the first time to set account + //若是第一次建立账户显示选择账户提示对话框 + showSelectAccountAlertDialog(); + } else { + // if the account has already been set, we need to promp + // user about the risk + //若是已经建立则显示修改对话框并进行修改操作 + showChangeAccountConfirmAlertDialog(); + } + } else { + //若在没有同步的情况下,则在toast中显示不能修改 + Toast.makeText(NotesPreferenceActivity.this, + R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT) + .show(); + } + return true; + } + }); + mAccountCategory.addPreference(accountPref);//根据新建首选项编辑新的账户分组 + } + /** + * @method loadSyncButton + * @description 设置按键的状态和最后同步的时间 + * @date: 12/23/2023 11:46 PM + * @author: YangYizhe + * @param + * @return + */ + private void loadSyncButton() { + Button syncButton = (Button) findViewById(R.id.preference_sync_button); + TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + //获取同步按钮控件和最终同步时间的的窗口 + // set button state + //设置按钮的状态 + if (GTaskSyncService.isSyncing()) { + //若是在同步状态下 + syncButton.setText(getString(R.string.preferences_button_sync_cancel)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.cancelSync(NotesPreferenceActivity.this); + } + });//设置按钮显示的文本为“取消同步”以及监听器 + } else { + syncButton.setText(getString(R.string.preferences_button_sync_immediately)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.startSync(NotesPreferenceActivity.this); + } + });//若是不同步则设置按钮显示的文本为“立即同步”以及对应监听器 + } + syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));//设置按键可用还是不可用 + // set last sync time + // 设置最终同步时间 + if (GTaskSyncService.isSyncing()) { + //若是在同步的情况下 + lastSyncTimeView.setText(GTaskSyncService.getProgressString()); + lastSyncTimeView.setVisibility(View.VISIBLE); + // 根据当前同步服务器设置时间显示框的文本以及可见性 + } else { + //若是非同步情况 + long lastSyncTime = getLastSyncTime(this); + if (lastSyncTime != 0) { + lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time, + DateFormat.format(getString(R.string.preferences_last_sync_time_format), + lastSyncTime))); + lastSyncTimeView.setVisibility(View.VISIBLE); + //则根据最后同步时间的信息来编辑时间显示框的文本内容和可见性 + } else { + //若时间为空直接设置为不可见状态 + lastSyncTimeView.setVisibility(View.GONE); + } + } + } + /** + * @method refreshUI + * @description + * 刷新标签界面 + * 调用上文设置账号和设置按键两个函数来实现 + * @date: 12/23/2023 11:46 PM + * @author: YangYizhe + */ + private void refreshUI() { + loadAccountPreference(); + loadSyncButton(); + } + /** + * @method showSelectAccountAlertDialog + * @description 显示账户选择的对话框并进行账户的设置 + * @date: 12/23/2023 11:47 PM + * @author: YangYizhe + * @param + * @return + */ + private void showSelectAccountAlertDialog() { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框 + + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); + TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); + titleTextView.setText(getString(R.string.preferences_dialog_select_account_title)); + TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); + subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));//设置标题以及子标题的内容 + dialogBuilder.setCustomTitle(titleView); + dialogBuilder.setPositiveButton(null, null);//设置对话框的自定义标题,建立一个YES的按钮 + Account[] accounts = getGoogleAccounts(); + String defAccount = getSyncAccountName(this);//获取同步账户信息 + mOriAccounts = accounts; + mHasAddedAccount = false; + + if (accounts.length > 0) { + //若账户不为空 + CharSequence[] items = new CharSequence[accounts.length]; + final CharSequence[] itemMapping = items; + int checkedItem = -1; + int index = 0; + for (Account account : accounts) { + if (TextUtils.equals(account.name, defAccount)) { + checkedItem = index;//在账户列表中查询到所需账户 + } + items[index++] = account.name; + } + dialogBuilder.setSingleChoiceItems(items, checkedItem, + //在对话框建立一个单选的复选框 + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setSyncAccount(itemMapping[which].toString()); + dialog.dismiss();//取消对话框 + refreshUI(); + } + });//建立对话框网络版的监听器 + } + + View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null); + dialogBuilder.setView(addAccountView);//给新加账户对话框设置自定义样式 + + final AlertDialog dialog = dialogBuilder.show();//显示对话框 + addAccountView.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mHasAddedAccount = true; + //将新加账户的hash置true + Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); + //建立网络建立组件 + intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] { + "gmail-ls" + }); + startActivityForResult(intent, -1); + //跳回上一个选项 + dialog.dismiss(); + } + });//建立新加账户对话框的监听器 + } + /** + * @method showChangeAccountConfirmAlertDialog + * @description 显示账户选择对话框和相关账户操作 + * @date: 12/23/2023 11:48 PM + * @author: YangYizhe + */ + private void showChangeAccountConfirmAlertDialog() { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框 + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); + TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); + titleTextView.setText(getString(R.string.preferences_dialog_change_account_title, + getSyncAccountName(this))); + TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); + subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));//根据同步修改的账户信息设置标题以及子标题的内容 + dialogBuilder.setCustomTitle(titleView);//设置对话框的自定义标题 + CharSequence[] menuItemArray = new CharSequence[] { + getString(R.string.preferences_menu_change_account), + getString(R.string.preferences_menu_remove_account), + getString(R.string.preferences_menu_cancel) + }; + dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() { + //设置对话框要显示的一个list,用于显示几个命令时,即change,remove,cancel + public void onClick(DialogInterface dialog, int which) { + //按键功能,由which来决定 + if (which == 0) { + //进入账户选择对话框 + showSelectAccountAlertDialog(); + } else if (which == 1) { + //删除账户并且跟新便签界面 + removeSyncAccount(); + refreshUI(); + } + } + }); + dialogBuilder.show();//显示对话框 + } + + /** + * @method getGoogleAccounts + * @description + * 获取谷歌账户 + * 通过账户管理器直接获取 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + */ + private Account[] getGoogleAccounts() { + AccountManager accountManager = AccountManager.get(this); + return accountManager.getAccountsByType("com.google"); + } + + /** + * @method setSyncAccount + * @description 设置同步账户 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + * @param account + */ + private void setSyncAccount(String account) { + if (!getSyncAccountName(this).equals(account)) { + //假如该账号不在同步账号列表中 + SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();//编辑共享的首选项 + if (account != null) { + editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account); + } else { + editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); + }//将该账号加入到首选项中 + + editor.commit();//提交修改的数据 + setLastSyncTime(this, 0);//将最后同步时间清零 + + // clean up local gtask related info + new Thread(new Runnable() { + public void run() { + ContentValues values = new ContentValues(); + values.put(NoteColumns.GTASK_ID, ""); + values.put(NoteColumns.SYNC_ID, 0); + getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); + } + }).start(); + //重置当地同步任务的信息 + + Toast.makeText(NotesPreferenceActivity.this, + getString(R.string.preferences_toast_success_set_accout, account), + Toast.LENGTH_SHORT).show(); + //将toast的文本信息置为“设置账户成功”并显示出来 + } + } + /** + * @method removeSyncAccount + * @description 删除同步账户 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + */ + private void removeSyncAccount() { + SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();//设置共享首选项 + + if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) { + editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);//假如当前首选项中有账户就删除 + } + if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) { + editor.remove(PREFERENCE_LAST_SYNC_TIME);//删除当前首选项中有账户时间 + } + editor.commit();//提交更新后的数据 + + // clean up local gtask related info + new Thread(new Runnable() { + public void run() { + ContentValues values = new ContentValues(); + values.put(NoteColumns.GTASK_ID, ""); + values.put(NoteColumns.SYNC_ID, 0); + getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); + } + }).start(); + //重置当地同步任务的信息 + } + /** + * @method getSyncAccountName + * @description + * 获取同步账户名称 + * 通过共享的首选项里的信息直接获取 + * @date: 12/23/2023 11:50 PM + * @author: YangYizhe + * @param context + */ + public static String getSyncAccountName(Context context) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); + } + /** + * @method setLastSyncTime + * @description 设置最终同步的时间 + * @date: 12/23/2023 11:50 PM + * @author: YangYizhe + * @param + * @return + */ + public static void setLastSyncTime(Context context, long time) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();// 从共享首选项中找到相关账户并获取其编辑器 + editor.putLong(PREFERENCE_LAST_SYNC_TIME, time); + editor.commit();//编辑最终同步时间并提交更新 + } + /** + * @method getLastSyncTime + * @description + * 获取最终同步时间 + * 通过共享的首选项里的信息直接获取 + * @date: 12/23/2023 11:51 PM + * @author: YangYizhe + * @param context + */ + public static long getLastSyncTime(Context context) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0); + } + + private class GTaskReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + refreshUI(); + if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) { + //获取随广播而来的Intent中的同步服务的数据 + TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + syncStatus.setText(intent + .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));//通过获取的数据在设置系统的状态 + } + + } + } + /** + * @method onOptionsItemSelected + * @description 处理菜单的选项 + * @date: 12/23/2023 11:52 PM + * @author: YangYizhe + * @param item + */ + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + //根据选项的id选择,这里只有一个主页 + case android.R.id.home: + Intent intent = new Intent(this, NotesListActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + //在主页情况下在创建连接组件intent,发出清空的信号并开始一个相应的activity + default: + return false; + } + } +} + \ No newline at end of file diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java new file mode 100644 index 0000000..d8eb50b --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.util.Log; +import android.widget.RemoteViews; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NoteEditActivity; +import net.micode.notes.ui.NotesListActivity; +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider + * @Description: 这个抽象类用作MiNote应用程序中笔记小部件的基础。它提供了在主屏幕上更新和管理笔记小部件的功能。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:53 PM + * @Version: 1.0 + */ +public abstract class NoteWidgetProvider extends AppWidgetProvider { + public static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.BG_COLOR_ID, + NoteColumns.SNIPPET + }; + + public static final int COLUMN_ID = 0; + public static final int COLUMN_BG_COLOR_ID = 1; + public static final int COLUMN_SNIPPET = 2; + + private static final String TAG = "NoteWidgetProvider"; + + @Override + public void onDeleted(Context context, int[] appWidgetIds) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + for (int i = 0; i < appWidgetIds.length; i++) { + context.getContentResolver().update(Notes.CONTENT_NOTE_URI, + values, + NoteColumns.WIDGET_ID + "=?", + new String[] { String.valueOf(appWidgetIds[i])}); + } + } + + private Cursor getNoteWidgetInfo(Context context, int widgetId) { + return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, + null); + } + + protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + update(context, appWidgetManager, appWidgetIds, false); + } + + private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, + boolean privacyMode) { + for (int i = 0; i < appWidgetIds.length; i++) { + if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + int bgId = ResourceParser.getDefaultBgId(context); + String snippet = ""; + Intent intent = new Intent(context, NoteEditActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); + + Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); + if (c != null && c.moveToFirst()) { + if (c.getCount() > 1) { + Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); + c.close(); + return; + } + snippet = c.getString(COLUMN_SNIPPET); + bgId = c.getInt(COLUMN_BG_COLOR_ID); + intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); + intent.setAction(Intent.ACTION_VIEW); + } else { + snippet = context.getResources().getString(R.string.widget_havenot_content); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + } + + if (c != null) { + c.close(); + } + + RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); + rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); + intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); + /** + * Generate the pending intent to start host for the widget + */ + PendingIntent pendingIntent = null; + if (privacyMode) { + rv.setTextViewText(R.id.widget_text, + context.getString(R.string.widget_under_visit_mode)); + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( + context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + } else { + rv.setTextViewText(R.id.widget_text, snippet); + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, + PendingIntent.FLAG_UPDATE_CURRENT); + } + + rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); + appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + } + } + } + + protected abstract int getBgResourceId(int bgId); + + protected abstract int getLayoutId(); + + protected abstract int getWidgetType(); +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java new file mode 100644 index 0000000..f3d5f1e --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Context; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.ResourceParser; + +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider_2x + * @Description: + * 这个类是NoteWidgetProvider的一个具体实现,用于实现2x大小的笔记小部件。 + * 它继承自NoteWidgetProvider,并提供特定于2x小部件的布局ID、背景资源和小部件类型。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:55 PM + * @Version: 1.0 + */ +public class NoteWidgetProvider_2x extends NoteWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + super.update(context, appWidgetManager, appWidgetIds); + } + + @Override + protected int getLayoutId() { + return R.layout.widget_2x; + } + + @Override + protected int getBgResourceId(int bgId) { + return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); + } + + @Override + protected int getWidgetType() { + return Notes.TYPE_WIDGET_2X; + } +} diff --git a/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java new file mode 100644 index 0000000..0c3ae50 --- /dev/null +++ b/src/Notes/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Context; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.ResourceParser; + +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider_4x + * @Description: + * 这个类是NoteWidgetProvider的一个具体实现,用于实现4x大小的笔记小部件。 + * 它继承自NoteWidgetProvider,并提供特定于4x小部件的布局ID、背景资源和小部件类型。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:56 PM + * @Version: 1.0 + */ +public class NoteWidgetProvider_4x extends NoteWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + super.update(context, appWidgetManager, appWidgetIds); + } + + protected int getLayoutId() { + return R.layout.widget_4x; + } + + @Override + protected int getBgResourceId(int bgId) { + return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); + } + + @Override + protected int getWidgetType() { + return Notes.TYPE_WIDGET_4X; + } +} diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 972f9a0..f8ccd9c 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,4 +1,20 @@ + + + + + android:label="@string/app_name" + android:launchMode="singleTop" + android:theme="@style/NoteTheme" + android:windowSoftInputMode="adjustPan" > + + android:label="@string/app_name" > + + + diff --git a/src/main/java/net/micode/notes/data/Contact.java b/src/main/java/net/micode/notes/data/Contact.java new file mode 100644 index 0000000..d65c239 --- /dev/null +++ b/src/main/java/net/micode/notes/data/Contact.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.data;//属于data这个包 + +import android.content.Context; +import android.database.Cursor; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; +import android.telephony.PhoneNumberUtils; +import android.util.Log; + +import java.util.HashMap; +/** + * @Package: net.micode.notes.data + * @ClassName: Contact + * @Description: + * Contact类用于查询联系人信息并进行缓存。 + * 该类包含一个静态的HashMap作为缓存,存储电话号码和对应的联系人名字。 + * 通过调用getContact方法可以根据给定的电话号码查询联系人名字。 + * 如果缓存中已经存在该电话号码对应的联系人名字,则直接返回缓存中的结果,否则通过查询数据库获取联系人名字并更新缓存。 + * 该类还定义了一个私有的SQL筛选语句用于查询联系人信息。 + * 注意:该类是线程不安全的,如果需要在多线程环境下使用,请做好同步控制 + * @Author: YangYizhe + * @CreateDate: 12/17/2023 10:10 AM + * @Version: 1.0 + */ +public class Contact { + /** + * 作为缓存,存储电话号码和对应的联系人名字 + */ + private static HashMap sContactCache; + private static final String TAG = "Contact";//设置日志TAG标签 + + //查询联系人的SQL筛选语句 + private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + + " AND " + Data.RAW_CONTACT_ID + " IN " + + "(SELECT raw_contact_id " + + " FROM phone_lookup" + + " WHERE min_match = '+')"; + //获取联系人 + public static String getContact(Context context, String phoneNumber) { + if(sContactCache == null) {/*如果缓存为空,就新建一个*/ + sContactCache = new HashMap(); + } + + if(sContactCache.containsKey(phoneNumber)) {/*如果缓存中已经有该电话号码对应的联系人名字,就直接返回*/ + return sContactCache.get(phoneNumber); + } + + String selection = CALLER_ID_SELECTION.replace("+", + PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));//将电话号码转换为最小匹配模式,用于筛选 + Cursor cursor = context.getContentResolver().query( + Data.CONTENT_URI, + new String [] { Phone.DISPLAY_NAME }, + selection,//使用筛选条件 + new String[] { phoneNumber }, + null); + + if (cursor != null && cursor.moveToFirst()) {//如果找到了符合条件的联系人 + try { + String name = cursor.getString(0);//获取联系人名字 + sContactCache.put(phoneNumber, name);//将电话号码和联系人名字添加到缓存中 + return name;//返回联系人名字 + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, " Cursor get string error " + e.toString()); + return null; + } finally { + cursor.close();//关闭游标 + } + } else {/*没找到*/ + Log.d(TAG, "No contact matched with number:" + phoneNumber); + return null; + } + } +} diff --git a/src/main/java/net/micode/notes/model/Note.java b/src/main/java/net/micode/notes/model/Note.java new file mode 100644 index 0000000..864da2c --- /dev/null +++ b/src/main/java/net/micode/notes/model/Note.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.model; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.OperationApplicationException; +import android.net.Uri; +import android.os.RemoteException; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.Notes.TextNote; + +import java.util.ArrayList; + +/** + * @Package: net.micode.notes.model + * @ClassName: Note + * @Description: 笔记类,用于操作和管理笔记数据 + * @Author: YangYizhe + * @CreateDate: 12/17/2023 10:06 AM + * @UpdateUser: none + * @UpdateDate: 12/17/2023 10:06 AM + * @UpdateRemark: none + * @Version: 1.0 + */ +public class Note { + private ContentValues mNoteDiffValues; + private NoteData mNoteData; + private static final String TAG = "Note"; + /** + * @method getNewNoteId + * @description 获取新的笔记ID,用于向数据库中添加新的笔记 + * @date: 12/20/2023 11:23 PM + * @author: YangYizhe + * @param folderId 文件夹Id + * @return noteId 新的笔记Id + */ + public static synchronized long getNewNoteId(Context context, long folderId) { + // Create a new note in the database + // 在数据库中创建一个新的笔记 + ContentValues values = new ContentValues(); + long createdTime = System.currentTimeMillis(); + values.put(NoteColumns.CREATED_DATE, createdTime); + values.put(NoteColumns.MODIFIED_DATE, createdTime); + values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + values.put(NoteColumns.PARENT_ID, folderId); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); + + long noteId = 0; + try { + noteId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "Get note id error :" + e.toString()); + noteId = 0; + } + if (noteId == -1) { + throw new IllegalStateException("Wrong note id:" + noteId); + } + return noteId; + } + + public Note() { + mNoteDiffValues = new ContentValues(); + mNoteData = new NoteData(); + } + /** + * @method setNoteValue + * @description 设置笔记的值 + * @date: 12/20/2023 11:31 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setNoteValue(String key, String value) { + mNoteDiffValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + /** + * @method setTextData + * @description 设置文本数据 + * @date: 12/20/2023 11:31 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setTextData(String key, String value) { + mNoteData.setTextData(key, value); + } + /** + * @method setTextDataId + * @description 设置文本数据ID + * @date: 12/20/2023 11:33 PM + * @author: YangYizhe + * @param id + */ + public void setTextDataId(long id) { + mNoteData.setTextDataId(id); + } + /** + * @method getTextDataId + * @description 获取文本数据Id + * @date: 12/20/2023 11:34 PM + * @author: YangYizhe + * @return mTextDataId 文本数据Id + */ + public long getTextDataId() { + return mNoteData.mTextDataId; + } + /** + * @method setCallDataId + * @description 设置通话记录数据ID + * @date: 12/20/2023 11:35 PM + * @author: YangYizhe + * @param id 通话记录数据id + */ + public void setCallDataId(long id) { + mNoteData.setCallDataId(id); + } + /** + * @method setCallData + * @description 设置通话记录数据 + * @date: 12/20/2023 11:36 PM + * @author: YangYizhe + * @param key + * @param value + */ + public void setCallData(String key, String value) { + mNoteData.setCallData(key, value); + } + /** + * @method isLocalModified + * @description 判断笔记是否有本地修改 + * @date: 12/20/2023 11:38 PM + * @author: YangYizhe + * @return bool 是否有本地修改 + */ + public boolean isLocalModified() { + return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); + } + /** + * @method syncNote + * @description 同步笔记,将本地修改的数据同步到服务器 + * @date: 12/20/2023 11:42 PM + * @author: YangYizhe + * @param context 上下文对象 + * @param noteId 笔记ID + * @return bool 是否同步成功 + */ + public boolean syncNote(Context context, long noteId) { + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + } + + if (!isLocalModified()) { + return true; + } + + /** + * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and + * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the + * note data info + */ + if (context.getContentResolver().update( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, + null) == 0) { + Log.e(TAG, "Update note error, should not happen"); + // Do not return, fall through + } + mNoteDiffValues.clear(); + + if (mNoteData.isLocalModified() + && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { + return false; + } + + return true; + } + + private class NoteData { + private long mTextDataId; + + private ContentValues mTextDataValues; + + private long mCallDataId; + + private ContentValues mCallDataValues; + + private static final String TAG = "NoteData"; + + public NoteData() { + mTextDataValues = new ContentValues(); + mCallDataValues = new ContentValues(); + mTextDataId = 0; + mCallDataId = 0; + } + + boolean isLocalModified() { + return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; + } + + void setTextDataId(long id) { + if(id <= 0) { + throw new IllegalArgumentException("Text data id should larger than 0"); + } + mTextDataId = id; + } + + void setCallDataId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("Call data id should larger than 0"); + } + mCallDataId = id; + } + + void setCallData(String key, String value) { + mCallDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + void setTextData(String key, String value) { + mTextDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + Uri pushIntoContentResolver(Context context, long noteId) { + /** + * Check for safety + */ + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + } + + ArrayList operationList = new ArrayList(); + ContentProviderOperation.Builder builder = null; + + if(mTextDataValues.size() > 0) { + mTextDataValues.put(DataColumns.NOTE_ID, noteId); + if (mTextDataId == 0) { + mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mTextDataValues); + try { + setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new text data fail with noteId" + noteId); + mTextDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mTextDataId)); + builder.withValues(mTextDataValues); + operationList.add(builder.build()); + } + mTextDataValues.clear(); + } + + if(mCallDataValues.size() > 0) { + mCallDataValues.put(DataColumns.NOTE_ID, noteId); + if (mCallDataId == 0) { + mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mCallDataValues); + try { + setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new call data fail with noteId" + noteId); + mCallDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mCallDataId)); + builder.withValues(mCallDataValues); + operationList.add(builder.build()); + } + mCallDataValues.clear(); + } + + if (operationList.size() > 0) { + try { + ContentProviderResult[] results = context.getContentResolver().applyBatch( + Notes.AUTHORITY, operationList); + return (results == null || results.length == 0 || results[0] == null) ? null + : ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId); + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } + } + return null; + } + } +} diff --git a/src/main/java/net/micode/notes/model/WorkingNote.java b/src/main/java/net/micode/notes/model/WorkingNote.java new file mode 100644 index 0000000..31061f9 --- /dev/null +++ b/src/main/java/net/micode/notes/model/WorkingNote.java @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.model; + +import android.appwidget.AppWidgetManager; +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.Notes.TextNote; +import net.micode.notes.tool.ResourceParser.NoteBgResources; + +/** + * @Package: net.micode.notes.model + * @ClassName: WorkingNote + * @Description: + * 工作笔记类,用于表示一条工作笔记的信息 + * Note 类是一个基本的笔记类,包含了笔记的基本信息,如标题、内容等 + * WorkingNote 类则是在 Note 类的基础上进行扩展,增加了一些与工作笔记相关的属性和方法,例如提醒日期、背景颜色、小部件等。 + * @Author: YangYizhe + * @CreateDate: 12/20/2023 11:48 PM + * @Version: 1.0 + */ +public class WorkingNote { + // Note for the working note + private Note mNote; + // Note Id + private long mNoteId; + // Note content + private String mContent; + // Note mode + private int mMode; + + private long mAlertDate; + + private long mModifiedDate; + + private int mBgColorId; + + private int mWidgetId; + + private int mWidgetType; + + private long mFolderId; + + private Context mContext; + + private static final String TAG = "WorkingNote"; + + private boolean mIsDeleted; + /** + * 笔记设置状态变化监听器 + */ + private NoteSettingChangedListener mNoteSettingStatusListener; + + public static final String[] DATA_PROJECTION = new String[] { + DataColumns.ID, + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + public static final String[] NOTE_PROJECTION = new String[] { + NoteColumns.PARENT_ID, + NoteColumns.ALERTED_DATE, + NoteColumns.BG_COLOR_ID, + NoteColumns.WIDGET_ID, + NoteColumns.WIDGET_TYPE, + NoteColumns.MODIFIED_DATE + }; + + private static final int DATA_ID_COLUMN = 0; + + private static final int DATA_CONTENT_COLUMN = 1; + + private static final int DATA_MIME_TYPE_COLUMN = 2; + + private static final int DATA_MODE_COLUMN = 3; + + private static final int NOTE_PARENT_ID_COLUMN = 0; + + private static final int NOTE_ALERTED_DATE_COLUMN = 1; + + private static final int NOTE_BG_COLOR_ID_COLUMN = 2; + + private static final int NOTE_WIDGET_ID_COLUMN = 3; + + private static final int NOTE_WIDGET_TYPE_COLUMN = 4; + + private static final int NOTE_MODIFIED_DATE_COLUMN = 5; + + // New note construct + /** + * @method WorkingNote + * @description 构造方法,创建一个新的工作笔记 + * @date: 12/20/2023 11:54 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param folderId 笔记所属的文件夹ID + */ + private WorkingNote(Context context, long folderId) { + mContext = context; + mAlertDate = 0; + mModifiedDate = System.currentTimeMillis(); + mFolderId = folderId; + mNote = new Note(); + mNoteId = 0; + mIsDeleted = false; + mMode = 0; + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + } + /** + * @method WorkingNote + * @description 构造方法,加载一个已存在的工作笔记 + * @date: 12/20/2023 11:54 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param noteId 笔记的ID + * @param folderId 笔记所属的文件夹ID + */ + // Existing note construct + private WorkingNote(Context context, long noteId, long folderId) { + mContext = context; + mNoteId = noteId; + mFolderId = folderId; + mIsDeleted = false; + mNote = new Note(); + loadNote(); + } + /** + * @method loadNote + * @description 加载笔记的详细信息 + * @date: 12/20/2023 11:55 PM + * @author: YangYizhe + */ + private void loadNote() { + Cursor cursor = mContext.getContentResolver().query( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, + null, null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); + mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); + mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); + mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); + mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); + mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); + } + cursor.close(); + } else { + Log.e(TAG, "No note with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note with id " + mNoteId); + } + loadNoteData(); + } + /** + * @method loadNoteData + * @description 加载笔记的Data + * @date: 12/20/2023 11:55 PM + * @author: YangYizhe + */ + private void loadNoteData() { + Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, + DataColumns.NOTE_ID + "=?", new String[] { + String.valueOf(mNoteId) + }, null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + String type = cursor.getString(DATA_MIME_TYPE_COLUMN); + if (DataConstants.NOTE.equals(type)) { + mContent = cursor.getString(DATA_CONTENT_COLUMN); + mMode = cursor.getInt(DATA_MODE_COLUMN); + mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); + } else if (DataConstants.CALL_NOTE.equals(type)) { + mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); + } else { + Log.d(TAG, "Wrong note type with type:" + type); + } + } while (cursor.moveToNext()); + } + cursor.close(); + } else { + Log.e(TAG, "No data with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); + } + } + /** + * @method createEmptyNote + * @description 创建一个空的工作笔记 + * @date: 12/20/2023 11:56 PM + * @author: YangYizhe + * @param context 上下文环境 + * @param folderId 笔记所属的文件夹ID + * @param widgetId 笔记的小部件ID + * @param widgetType 笔记的小部件类型 + * @param defaultBgColorId 笔记的默认背景颜色ID + * @return note 创建的空的工作笔记对象 + */ + public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, + int widgetType, int defaultBgColorId) { + WorkingNote note = new WorkingNote(context, folderId); + note.setBgColorId(defaultBgColorId); + note.setWidgetId(widgetId); + note.setWidgetType(widgetType); + return note; + } + + public static WorkingNote load(Context context, long id) { + return new WorkingNote(context, id, 0); + } + + public synchronized boolean saveNote() { + if (isWorthSaving()) { + if (!existInDatabase()) { + if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { + Log.e(TAG, "Create new note fail with id:" + mNoteId); + return false; + } + } + + mNote.syncNote(mContext, mNoteId); + + /** + * Update widget content if there exist any widget of this note + */ + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + return true; + } else { + return false; + } + } + + public boolean existInDatabase() { + return mNoteId > 0; + } + + private boolean isWorthSaving() { + if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) + || (existInDatabase() && !mNote.isLocalModified())) { + return false; + } else { + return true; + } + } + + public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { + mNoteSettingStatusListener = l; + } + + public void setAlertDate(long date, boolean set) { + if (date != mAlertDate) { + mAlertDate = date; + mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate)); + } + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onClockAlertChanged(date, set); + } + } + + public void markDeleted(boolean mark) { + mIsDeleted = mark; + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + } + + public void setBgColorId(int id) { + if (id != mBgColorId) { + mBgColorId = id; + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onBackgroundColorChanged(); + } + mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); + } + } + + public void setCheckListMode(int mode) { + if (mMode != mode) { + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); + } + mMode = mode; + mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); + } + } + + public void setWidgetType(int type) { + if (type != mWidgetType) { + mWidgetType = type; + mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); + } + } + + public void setWidgetId(int id) { + if (id != mWidgetId) { + mWidgetId = id; + mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); + } + } + + public void setWorkingText(String text) { + if (!TextUtils.equals(mContent, text)) { + mContent = text; + mNote.setTextData(DataColumns.CONTENT, mContent); + } + } + + public void convertToCallNote(String phoneNumber, long callDate) { + mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); + mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); + mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); + } + + public boolean hasClockAlert() { + return (mAlertDate > 0 ? true : false); + } + + public String getContent() { + return mContent; + } + + public long getAlertDate() { + return mAlertDate; + } + + public long getModifiedDate() { + return mModifiedDate; + } + + public int getBgColorResId() { + return NoteBgResources.getNoteBgResource(mBgColorId); + } + + public int getBgColorId() { + return mBgColorId; + } + + public int getTitleBgResId() { + return NoteBgResources.getNoteTitleBgResource(mBgColorId); + } + + public int getCheckListMode() { + return mMode; + } + + public long getNoteId() { + return mNoteId; + } + + public long getFolderId() { + return mFolderId; + } + + public int getWidgetId() { + return mWidgetId; + } + + public int getWidgetType() { + return mWidgetType; + } + + public interface NoteSettingChangedListener { + /** + * Called when the background color of current note has just changed + */ + void onBackgroundColorChanged(); + + /** + * Called when user set clock + */ + void onClockAlertChanged(long date, boolean set); + + /** + * Call when user create note from widget + */ + void onWidgetChanged(); + + /** + * Call when switch between check list mode and normal mode + * @param oldMode is previous mode before change + * @param newMode is new mode + */ + void onCheckListModeChanged(int oldMode, int newMode); + } +} diff --git a/src/main/java/net/micode/notes/tool/BackupUtils.java b/src/main/java/net/micode/notes/tool/BackupUtils.java new file mode 100644 index 0000000..39f6ec4 --- /dev/null +++ b/src/main/java/net/micode/notes/tool/BackupUtils.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.tool; + +import android.content.Context; +import android.database.Cursor; +import android.os.Environment; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.util.Log; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + + +public class BackupUtils { + private static final String TAG = "BackupUtils"; + // Singleton stuff + private static BackupUtils sInstance; + + public static synchronized BackupUtils getInstance(Context context) { + if (sInstance == null) { + sInstance = new BackupUtils(context); + } + return sInstance; + } + + /** + * Following states are signs to represents backup or restore + * status + */ + // Currently, the sdcard is not mounted + public static final int STATE_SD_CARD_UNMOUONTED = 0; + // The backup file not exist + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + // The data is not well formated, may be changed by other programs + public static final int STATE_DATA_DESTROIED = 2; + // Some run-time exception which causes restore or backup fails + public static final int STATE_SYSTEM_ERROR = 3; + // Backup or restore success + public static final int STATE_SUCCESS = 4; + + private TextExport mTextExport; + + private BackupUtils(Context context) { + mTextExport = new TextExport(context); + } + + private static boolean externalStorageAvailable() { + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } + + public int exportToText() { + return mTextExport.exportToText(); + } + + public String getExportedTextFileName() { + return mTextExport.mFileName; + } + + public String getExportedTextFileDir() { + return mTextExport.mFileDirectory; + } + + private static class TextExport { + private static final String[] NOTE_PROJECTION = { + NoteColumns.ID, + NoteColumns.MODIFIED_DATE, + NoteColumns.SNIPPET, + NoteColumns.TYPE + }; + + private static final int NOTE_COLUMN_ID = 0; + + private static final int NOTE_COLUMN_MODIFIED_DATE = 1; + + private static final int NOTE_COLUMN_SNIPPET = 2; + + private static final String[] DATA_PROJECTION = { + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + private static final int DATA_COLUMN_CONTENT = 0; + + private static final int DATA_COLUMN_MIME_TYPE = 1; + + private static final int DATA_COLUMN_CALL_DATE = 2; + + private static final int DATA_COLUMN_PHONE_NUMBER = 4; + + private final String [] TEXT_FORMAT; + private static final int FORMAT_FOLDER_NAME = 0; + private static final int FORMAT_NOTE_DATE = 1; + private static final int FORMAT_NOTE_CONTENT = 2; + + private Context mContext; + private String mFileName; + private String mFileDirectory; + + public TextExport(Context context) { + TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); + mContext = context; + mFileName = ""; + mFileDirectory = ""; + } + + private String getFormat(int id) { + return TEXT_FORMAT[id]; + } + + /** + * Export the folder identified by folder id to text + */ + private void exportFolderToText(String folderId, PrintStream ps) { + // Query notes belong to this folder + Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { + folderId + }, null); + + if (notesCursor != null) { + if (notesCursor.moveToFirst()) { + do { + // Print note's last modified date + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // Query data belong to this note + String noteId = notesCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (notesCursor.moveToNext()); + } + notesCursor.close(); + } + } + + /** + * Export note identified by id to a print stream + */ + private void exportNoteToText(String noteId, PrintStream ps) { + Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, + DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { + noteId + }, null); + + if (dataCursor != null) { + if (dataCursor.moveToFirst()) { + do { + String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); + if (DataConstants.CALL_NOTE.equals(mimeType)) { + // Print phone number + String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); + long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); + String location = dataCursor.getString(DATA_COLUMN_CONTENT); + + if (!TextUtils.isEmpty(phoneNumber)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + phoneNumber)); + } + // Print call date + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat + .format(mContext.getString(R.string.format_datetime_mdhm), + callDate))); + // Print call attachment location + if (!TextUtils.isEmpty(location)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + location)); + } + } else if (DataConstants.NOTE.equals(mimeType)) { + String content = dataCursor.getString(DATA_COLUMN_CONTENT); + if (!TextUtils.isEmpty(content)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + content)); + } + } + } while (dataCursor.moveToNext()); + } + dataCursor.close(); + } + // print a line separator between note + try { + ps.write(new byte[] { + Character.LINE_SEPARATOR, Character.LETTER_NUMBER + }); + } catch (IOException e) { + Log.e(TAG, e.toString()); + } + } + + /** + * Note will be exported as text which is user readable + */ + public int exportToText() { + if (!externalStorageAvailable()) { + Log.d(TAG, "Media was not mounted"); + return STATE_SD_CARD_UNMOUONTED; + } + + PrintStream ps = getExportToTextPrintStream(); + if (ps == null) { + Log.e(TAG, "get print stream error"); + return STATE_SYSTEM_ERROR; + } + // First export folder and its notes + Cursor folderCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); + + if (folderCursor != null) { + if (folderCursor.moveToFirst()) { + do { + // Print folder's name + String folderName = ""; + if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { + folderName = mContext.getString(R.string.call_record_folder_name); + } else { + folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); + } + if (!TextUtils.isEmpty(folderName)) { + ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); + } + String folderId = folderCursor.getString(NOTE_COLUMN_ID); + exportFolderToText(folderId, ps); + } while (folderCursor.moveToNext()); + } + folderCursor.close(); + } + + // Export notes in root's folder + Cursor noteCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + + "=0", null, null); + + if (noteCursor != null) { + if (noteCursor.moveToFirst()) { + do { + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // Query data belong to this note + String noteId = noteCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (noteCursor.moveToNext()); + } + noteCursor.close(); + } + ps.close(); + + return STATE_SUCCESS; + } + + /** + * Get a print stream pointed to the file {@generateExportedTextFile} + */ + private PrintStream getExportToTextPrintStream() { + File file = generateFileMountedOnSDcard(mContext, R.string.file_path, + R.string.file_name_txt_format); + if (file == null) { + Log.e(TAG, "create file to exported failed"); + return null; + } + mFileName = file.getName(); + mFileDirectory = mContext.getString(R.string.file_path); + PrintStream ps = null; + try { + FileOutputStream fos = new FileOutputStream(file); + ps = new PrintStream(fos); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } + return ps; + } + } + + /** + * Generate the text file to store imported data + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + StringBuilder sb = new StringBuilder(); + sb.append(Environment.getExternalStorageDirectory()); + sb.append(context.getString(filePathResId)); + File filedir = new File(sb.toString()); + sb.append(context.getString( + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), + System.currentTimeMillis()))); + File file = new File(sb.toString()); + + try { + if (!filedir.exists()) { + filedir.mkdir(); + } + if (!file.exists()) { + file.createNewFile(); + } + return file; + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } +} + + diff --git a/src/main/java/net/micode/notes/tool/DataUtils.java b/src/main/java/net/micode/notes/tool/DataUtils.java new file mode 100644 index 0000000..2a14982 --- /dev/null +++ b/src/main/java/net/micode/notes/tool/DataUtils.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.tool; + +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.os.RemoteException; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.CallNote; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; + +import java.util.ArrayList; +import java.util.HashSet; + + +public class DataUtils { + public static final String TAG = "DataUtils"; + public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true; + } + if (ids.size() == 0) { + Log.d(TAG, "no id is in the hashset"); + return true; + } + + ArrayList operationList = new ArrayList(); + for (long id : ids) { + if(id == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Don't delete system folder root"); + continue; + } + ContentProviderOperation.Builder builder = ContentProviderOperation + .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + operationList.add(builder.build()); + } + try { + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false; + } + return true; + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } + return false; + } + + public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.PARENT_ID, desFolderId); + values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); + } + + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, + long folderId) { + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true; + } + + ArrayList operationList = new ArrayList(); + for (long id : ids) { + ContentProviderOperation.Builder builder = ContentProviderOperation + .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + builder.withValue(NoteColumns.PARENT_ID, folderId); + builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); + operationList.add(builder.build()); + } + + try { + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false; + } + return true; + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } + return false; + } + + /** + * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + */ + public static int getUserFolderCount(ContentResolver resolver) { + Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { "COUNT(*)" }, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, + null); + + int count = 0; + if(cursor != null) { + if(cursor.moveToFirst()) { + try { + count = cursor.getInt(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "get folder count failed:" + e.toString()); + } finally { + cursor.close(); + } + } + } + return count; + } + + public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, + new String [] {String.valueOf(type)}, + null); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, null, null, null); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), + null, null, null, null); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.SNIPPET + "=?", + new String[] { name }, null); + boolean exist = false; + if(cursor != null) { + if(cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, + NoteColumns.PARENT_ID + "=?", + new String[] { String.valueOf(folderId) }, + null); + + HashSet set = null; + if (c != null) { + if (c.moveToFirst()) { + set = new HashSet(); + do { + try { + AppWidgetAttribute widget = new AppWidgetAttribute(); + widget.widgetId = c.getInt(0); + widget.widgetType = c.getInt(1); + set.add(widget); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, e.toString()); + } + } while (c.moveToNext()); + } + c.close(); + } + return set; + } + + public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.PHONE_NUMBER }, + CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", + new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + null); + + if (cursor != null && cursor.moveToFirst()) { + try { + return cursor.getString(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call number fails " + e.toString()); + } finally { + cursor.close(); + } + } + return ""; + } + + public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.NOTE_ID }, + CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + + CallNote.PHONE_NUMBER + ",?)", + new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, + null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + try { + return cursor.getLong(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call note id fails " + e.toString()); + } + } + cursor.close(); + } + return 0; + } + + public static String getSnippetById(ContentResolver resolver, long noteId) { + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, + new String [] { NoteColumns.SNIPPET }, + NoteColumns.ID + "=?", + new String [] { String.valueOf(noteId)}, + null); + + if (cursor != null) { + String snippet = ""; + if (cursor.moveToFirst()) { + snippet = cursor.getString(0); + } + cursor.close(); + return snippet; + } + throw new IllegalArgumentException("Note is not found with id: " + noteId); + } + + public static String getFormattedSnippet(String snippet) { + if (snippet != null) { + snippet = snippet.trim(); + int index = snippet.indexOf('\n'); + if (index != -1) { + snippet = snippet.substring(0, index); + } + } + return snippet; + } +} diff --git a/src/main/java/net/micode/notes/tool/GTaskStringUtils.java b/src/main/java/net/micode/notes/tool/GTaskStringUtils.java new file mode 100644 index 0000000..666b729 --- /dev/null +++ b/src/main/java/net/micode/notes/tool/GTaskStringUtils.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.tool; + +public class GTaskStringUtils { + + public final static String GTASK_JSON_ACTION_ID = "action_id"; + + public final static String GTASK_JSON_ACTION_LIST = "action_list"; + + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; + + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; + + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; + + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; + + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; + + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; + + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; + + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; + + public final static String GTASK_JSON_COMPLETED = "completed"; + + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; + + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; + + public final static String GTASK_JSON_DELETED = "deleted"; + + public final static String GTASK_JSON_DEST_LIST = "dest_list"; + + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; + + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; + + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; + + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; + + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; + + public final static String GTASK_JSON_ID = "id"; + + public final static String GTASK_JSON_INDEX = "index"; + + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; + + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; + + public final static String GTASK_JSON_LIST_ID = "list_id"; + + public final static String GTASK_JSON_LISTS = "lists"; + + public final static String GTASK_JSON_NAME = "name"; + + public final static String GTASK_JSON_NEW_ID = "new_id"; + + public final static String GTASK_JSON_NOTES = "notes"; + + public final static String GTASK_JSON_PARENT_ID = "parent_id"; + + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; + + public final static String GTASK_JSON_RESULTS = "results"; + + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; + + public final static String GTASK_JSON_TASKS = "tasks"; + + public final static String GTASK_JSON_TYPE = "type"; + + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; + + public final static String GTASK_JSON_TYPE_TASK = "TASK"; + + public final static String GTASK_JSON_USER = "user"; + + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; + + public final static String FOLDER_DEFAULT = "Default"; + + public final static String FOLDER_CALL_NOTE = "Call_Note"; + + public final static String FOLDER_META = "METADATA"; + + public final static String META_HEAD_GTASK_ID = "meta_gid"; + + public final static String META_HEAD_NOTE = "meta_note"; + + public final static String META_HEAD_DATA = "meta_data"; + + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; + +} diff --git a/src/main/java/net/micode/notes/tool/ResourceParser.java b/src/main/java/net/micode/notes/tool/ResourceParser.java new file mode 100644 index 0000000..1ad3ad6 --- /dev/null +++ b/src/main/java/net/micode/notes/tool/ResourceParser.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.tool; + +import android.content.Context; +import android.preference.PreferenceManager; + +import net.micode.notes.R; +import net.micode.notes.ui.NotesPreferenceActivity; + +public class ResourceParser { + + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4; + + public static final int BG_DEFAULT_COLOR = YELLOW; + + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3; + + public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; + + public static class NoteBgResources { + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red + }; + + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red + }; + + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + } + + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + } + } + + public static int getDefaultBgId(Context context) { + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length); + } else { + return BG_DEFAULT_COLOR; + } + } + + public static class NoteItemBgResources { + private final static int [] BG_FIRST_RESOURCES = new int [] { + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up + }; + + private final static int [] BG_NORMAL_RESOURCES = new int [] { + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle + }; + + private final static int [] BG_LAST_RESOURCES = new int [] { + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, + }; + + private final static int [] BG_SINGLE_RESOURCES = new int [] { + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single + }; + + public static int getNoteBgFirstRes(int id) { + return BG_FIRST_RESOURCES[id]; + } + + public static int getNoteBgLastRes(int id) { + return BG_LAST_RESOURCES[id]; + } + + public static int getNoteBgSingleRes(int id) { + return BG_SINGLE_RESOURCES[id]; + } + + public static int getNoteBgNormalRes(int id) { + return BG_NORMAL_RESOURCES[id]; + } + + public static int getFolderBgRes() { + return R.drawable.list_folder; + } + } + + public static class WidgetBgResources { + private final static int [] BG_2X_RESOURCES = new int [] { + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, + }; + + public static int getWidget2xBgResource(int id) { + return BG_2X_RESOURCES[id]; + } + + private final static int [] BG_4X_RESOURCES = new int [] { + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red + }; + + public static int getWidget4xBgResource(int id) { + return BG_4X_RESOURCES[id]; + } + } + + public static class TextAppearanceResources { + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper + }; + + public static int getTexAppearanceResource(int id) { + /** + * HACKME: Fix bug of store the resource id in shared preference. + * The id may larger than the length of resources, in this case, + * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + */ + if (id >= TEXTAPPEARANCE_RESOURCES.length) { + return BG_DEFAULT_FONT_SIZE; + } + return TEXTAPPEARANCE_RESOURCES[id]; + } + + public static int getResourcesSize() { + return TEXTAPPEARANCE_RESOURCES.length; + } + } +} diff --git a/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java b/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java new file mode 100644 index 0000000..96f28bf --- /dev/null +++ b/src/main/java/net/micode/notes/ui/AlarmAlertActivity.java @@ -0,0 +1,201 @@ +package net.micode.notes.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface.OnDismissListener; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.Window; +import android.view.WindowManager; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; + +import java.io.IOException; +/** + * @Package: net.micode.notes.ui + * @ClassName: AlarmAlertActivity + * @Description: 闹钟提醒界面 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:02 AM + * @Version: 1.0 + */ +public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + private long mNoteId; //文本在数据库存储中的ID号 + private String mSnippet; //闹钟提示时出现的文本片段 + private static final int SNIPPET_PREW_MAX_LEN = 60; + MediaPlayer mPlayer; + /** + * @method onCreate + * @description 当 Activity 创建时调用的生命周期方法 + * @date: 12/21/2023 12:05 AM + * @author: YangYizhe + * @param savedInstanceState 保存 Activity 状态的 Bundle 对象 + * @return null + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_NO_TITLE);//设置界面显示——无标题 + + final Window win = getWindow(); + + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);//设置窗体属性——在锁屏时显示 + + if (!isScreenOn()) { + win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON//保持点亮、点亮屏幕、允许点亮时解锁 + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); + } + + Intent intent = getIntent();//获取传递的 Intent + + try { + // 从 Intent 中获取数据并处理——获取标签 ID + mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + // 根据 ID 从数据库中获取标签内容 + mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + // 判断标签片段是否达到符合长度 + mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, + SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) + : mSnippet; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return; + } + + mPlayer = new MediaPlayer(); + if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + showActionDialog();// 显示对话框 + playAlarmSound();// 播放闹钟提示音 + } else { + finish();// 结束当前 Activity + } + } + /** + * @method isScreenOn + * @description + * 判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型 + * @date: 12/23/2023 11:21 PM + * @author: YangYizhe + * @param + * @return + */ + private boolean isScreenOn() { + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + return pm.isScreenOn(); + } + /** + * @method playAlarmSound + * @description + * 播放闹钟提示音 + * @date: 12/23/2023 11:21 PM + * @author: YangYizhe + */ + private void playAlarmSound() { + Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + //调用系统的铃声管理URI,得到闹钟提示音 + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + + if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { + mPlayer.setAudioStreamType(silentModeStreams); + } else { + mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + } + try { + mPlayer.setDataSource(this, url); + mPlayer.prepare(); + mPlayer.setLooping(true);//设置是否循环播放 + mPlayer.start();//开始播放 + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + /** + * @method showActionDialog + * @description + * AlertDialog的构造方法全部是Protected的 + * 所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。 + * 要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法 + * 如这里的dialog就是新建了一个AlertDialog + * @date: 12/23/2023 11:28 PM + * @author: YangYizhe + */ + private void showActionDialog() { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(R.string.app_name);//为对话框设置标题 + dialog.setMessage(mSnippet);//为对话框设置内容 + dialog.setPositiveButton(R.string.notealert_ok, this);//给对话框添加"Yes"按钮 + if (isScreenOn()) { + dialog.setNegativeButton(R.string.notealert_enter, this);//对话框添加"No"按钮 + } + dialog.show().setOnDismissListener(this); + } + /** + * @method onClick + * @description 处理点击事件 + * @date: 12/23/2023 11:27 PM + * @author: YangYizhe + * @param dialog + * @param which + */ + public void onClick(DialogInterface dialog, int which) { + switch (which) {//用which来选择click后下一步的操作 + case DialogInterface.BUTTON_NEGATIVE://这是取消操作 + Intent intent = new Intent(this, NoteEditActivity.class);//实现两个类间的数据传输 + intent.setAction(Intent.ACTION_VIEW);//设置动作属性 + intent.putExtra(Intent.EXTRA_UID, mNoteId);//实现key-value对 EXTRA_UID为key;mNoteId为键 + startActivity(intent);//开始动作 + break; + default: + break; + } + } + /** + * @method onDismiss + * @description 忽略 + * @date: 12/23/2023 11:25 PM + * @author: YangYizhe + * @param dialog + */ + public void onDismiss(DialogInterface dialog) { + stopAlarmSound();//停止闹钟声音 + finish(); + } + /** + * @method stopAlarmSound + * @description 停止闹钟的声音 + * @date: 12/23/2023 11:26 PM + * @author: YangYizhe + */ + private void stopAlarmSound() { + if (mPlayer != null) { + mPlayer.stop();//停止播放 + mPlayer.release();//释放MediaPlayer对象 + mPlayer = null; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java b/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java new file mode 100644 index 0000000..1982fda --- /dev/null +++ b/src/main/java/net/micode/notes/ui/AlarmInitReceiver.java @@ -0,0 +1,57 @@ +package net.micode.notes.ui; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; + +/** + * @Package: net.micode.notes.ui + * @ClassName: AlarmInitReceiver + * @Description: + * AlarmInitReceiver 是一个广播接收器(BroadcastReceiver)的类 + * 广播接收器是 Android 中常用的一种组件,用于接收并处理系统或应用发送的广播消息 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:09 AM + * @Version: 1.0 + */ +public class AlarmInitReceiver extends BroadcastReceiver { + private static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.ALERTED_DATE + };//对数据库的操作,调用标签ID和闹钟时间 + private static final int COLUMN_ID = 0; + private static final int COLUMN_ALERTED_DATE = 1; + + @Override + public void onReceive(Context context, Intent intent) { + long currentDate = System.currentTimeMillis();//System.currentTimeMillis()产生一个当前的毫秒 + Cursor c = context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.ALERTED_DATE + ">? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, + new String[] { String.valueOf(currentDate) }, + null);//将long变量currentDate转化为字符串 + //Cursor在这里的作用是通过查找数据库中的标签内容,找到和当前系统时间相等的标签 + + if (c != null) { + if (c.moveToFirst()) { + do { + long alertDate = c.getLong(COLUMN_ALERTED_DATE); + Intent sender = new Intent(context, AlarmReceiver.class); + sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + AlarmManager alermManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); + } while (c.moveToNext()); + } + c.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/DateTimePicker.java b/src/main/java/net/micode/notes/ui/DateTimePicker.java new file mode 100644 index 0000000..9cf4ba6 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/DateTimePicker.java @@ -0,0 +1,518 @@ +package net.micode.notes.ui; + +import java.text.DateFormatSymbols; +import java.util.Calendar; + +import net.micode.notes.R; + + +import android.content.Context; +import android.text.format.DateFormat; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.NumberPicker; +/** + * @Package: net.micode.notes.ui + * @ClassName: DateTimePicker + * @Description: 继承自FrameLayout,实现了日期和时间的选择功能 + * 提供一个用户界面,让用户可以方便地选择日期和时间,并且能够监听用户对日期和时间的改变 + * 构造方法,包括默认构造方法和带参数的构造方法,用于初始化日期选择器的界面和属性; + * 一系列的回调方法,用于监听日期和时间的改变,包括日期选择、小时选择、分钟选择、上午/下午选择等; + * 一些公开的接口方法,用于设置当前日期、时间,设置24小时模式或12小时模式的切换等; + * 辅助方法,用于更新日期、小时、上午/下午选择器的界面显示和属性; + * 回调接口OnDateTimeChangedListener,用于监听日期和时间的改变事件。 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:18 AM + * @Version: 1.0 + */ +public class DateTimePicker extends FrameLayout { + //FrameLayout是布局模板之一 + private static final boolean DEFAULT_ENABLE_STATE = true; + + private static final int HOURS_IN_HALF_DAY = 12; + private static final int HOURS_IN_ALL_DAY = 24; + private static final int DAYS_IN_ALL_WEEK = 7; + private static final int DATE_SPINNER_MIN_VAL = 0; + private static final int DATE_SPINNER_MAX_VAL = DAYS_IN_ALL_WEEK - 1; + private static final int HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW = 0; + private static final int HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW = 23; + private static final int HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW = 1; + private static final int HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW = 12; + private static final int MINUT_SPINNER_MIN_VAL = 0; + private static final int MINUT_SPINNER_MAX_VAL = 59; + private static final int AMPM_SPINNER_MIN_VAL = 0; + private static final int AMPM_SPINNER_MAX_VAL = 1; + /** + * 初始化控件 + * NumberPicker是数字选择器 + * 这里定义的四个变量全部是在设置闹钟时需要选择的变量(如日期、时、分、上午或者下午) + */ + private final NumberPicker mDateSpinner; + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private Calendar mDate;//定义了Calendar类型的变量mDate,用于操作时间 + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + private boolean mIsAm; + + private boolean mIs24HourView; + + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + private boolean mInitialising; + + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mDate.add(Calendar.DAY_OF_YEAR, newVal - oldVal); + updateDateControl(); + onDateTimeChanged(); + } + };//OnValueChangeListener,这是时间改变监听器,这里主要是对日期的监听 + + + private NumberPicker.OnValueChangeListener mOnHourChangedListener = new NumberPicker.OnValueChangeListener() { + //这里是对 小时(Hour) 的监听 + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + boolean isDateChanged = false; + Calendar cal = Calendar.getInstance(); + //声明一个Calendar的变量cal,便于后续的操作 + if (!mIs24HourView) { + if (!mIsAm && oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + //这里是对于12小时制时,晚上11点和12点交替时对日期的更改 + } else if (mIsAm && oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 + if (oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY || + oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + }//这里是对于12小时制时,中午11点和12点交替时对AM和PM的更改 + } else { + if (oldVal == HOURS_IN_ALL_DAY - 1 && newVal == 0) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, 1); + isDateChanged = true; + //这里是对于24小时制时,晚上11点和12点交替时对日期的更改 + } else if (oldVal == 0 && newVal == HOURS_IN_ALL_DAY - 1) { + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -1); + isDateChanged = true; + } + } //这里是对于12小时制时,凌晨11点和12点交替时对日期的更改 + int newHour = mHourSpinner.getValue() % HOURS_IN_HALF_DAY + (mIsAm ? 0 : HOURS_IN_HALF_DAY); + //通过数字选择器对newHour的赋值 + mDate.set(Calendar.HOUR_OF_DAY, newHour); + //通过set函数将新的Hour值传给mDate + onDateTimeChanged(); + if (isDateChanged) { + setCurrentYear(cal.get(Calendar.YEAR)); + setCurrentMonth(cal.get(Calendar.MONTH)); + setCurrentDay(cal.get(Calendar.DAY_OF_MONTH)); + } + } + }; + + private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + //这里是对 分钟(Minute)改变的监听 + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + int offset = 0; + //设置offset,作为小时改变的一个记录数据 + if (oldVal == maxValue && newVal == minValue) { + offset += 1; + } else if (oldVal == minValue && newVal == maxValue) { + offset -= 1; + } + //如果原值为59,新值为0,则offset加1 + //如果原值为0,新值为59,则offset减1 + if (offset != 0) { + mDate.add(Calendar.HOUR_OF_DAY, offset); + mHourSpinner.setValue(getCurrentHour()); + updateDateControl(); + int newHour = getCurrentHourOfDay(); + if (newHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + updateAmPmControl(); + } else { + mIsAm = true; + updateAmPmControl(); + } + } + mDate.set(Calendar.MINUTE, newVal); + onDateTimeChanged(); + } + }; + + private NumberPicker.OnValueChangeListener mOnAmPmChangedListener = new NumberPicker.OnValueChangeListener() { + //对AM和PM的监听 + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + mIsAm = !mIsAm; + if (mIsAm) { + mDate.add(Calendar.HOUR_OF_DAY, -HOURS_IN_HALF_DAY); + } else { + mDate.add(Calendar.HOUR_OF_DAY, HOURS_IN_HALF_DAY); + } + updateAmPmControl(); + onDateTimeChanged(); + } + }; + + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + /** + * 构造方法 + */ + public DateTimePicker(Context context) { + this(context, System.currentTimeMillis());//通过对数据库的访问,获取当前的系统时间 + } + + public DateTimePicker(Context context, long date) { + this(context, date, DateFormat.is24HourFormat(context));//上面函数的得到的是一个天文数字(1970至今的秒数),需要DateFormat将其变得有意义 + } + + public DateTimePicker(Context context, long date, boolean is24HourView) { + super(context); + mDate = Calendar.getInstance();//获取系统时间 + mInitialising = true; + mIsAm = getCurrentHourOfDay() >= HOURS_IN_HALF_DAY; + inflate(context, R.layout.datetime_picker, this); + /* + * 如果当前Activity里用到别的layout,比如对话框layout + * 还要设置这个layout上的其他组件的内容,就必须用inflate()方法先将对话框的layout找出来 + * 然后再用findViewById()找到它上面的其它组件 + */ + mDateSpinner = (NumberPicker) findViewById(R.id.date); + mDateSpinner.setMinValue(DATE_SPINNER_MIN_VAL); + mDateSpinner.setMaxValue(DATE_SPINNER_MAX_VAL); + mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); + + mHourSpinner = (NumberPicker) findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(MINUT_SPINNER_MIN_VAL); + mMinuteSpinner.setMaxValue(MINUT_SPINNER_MAX_VAL); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); + + String[] stringsForAmPm = new DateFormatSymbols().getAmPmStrings(); + mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm); + mAmPmSpinner.setMinValue(AMPM_SPINNER_MIN_VAL); + mAmPmSpinner.setMaxValue(AMPM_SPINNER_MAX_VAL); + mAmPmSpinner.setDisplayedValues(stringsForAmPm); + mAmPmSpinner.setOnValueChangedListener(mOnAmPmChangedListener); + + // update controls to initial state + updateDateControl(); + updateHourControl(); + updateAmPmControl(); + + set24HourView(is24HourView); + + // set to current time + setCurrentDate(date); + + setEnabled(isEnabled()); + + // set the content descriptions + mInitialising = false; + } + + /** + * @method setEnabled + * @description + * 用于设置是否启用日期选择器控件的功能 + * 先通过传入的参数enabled判断是否需要改变控件的启用状态。 + * 如果传入的参数和当前的启用状态相同,则直接返回,不进行任何操作 + * 如果传入的参数和当前的启用状态不同,则调用父类的setEnabled方法,来设置整个日期选择器控件的启用状态 + * 分别设置日期选择、分钟选择、小时选择、上午/下午选择这几个子控件的启用状态,即调用对应的setEnabled方法,并将enabled参数传入 + * @date: 12/21/2023 12:27 AM + * @author: YangYizhe + * @param enabled + */ + @Override + public void setEnabled(boolean enabled) { + if (mIsEnabled == enabled) { + return; + } + super.setEnabled(enabled); + mDateSpinner.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + mHourSpinner.setEnabled(enabled); + mAmPmSpinner.setEnabled(enabled); + mIsEnabled = enabled; + } + @Override + public boolean isEnabled() { + return mIsEnabled; + } + + /** + * Get the current date in millis + * + * @return the current date in millis + */ + public long getCurrentDateInTimeMillis() { + return mDate.getTimeInMillis(); + }//实现函数——得到当前的秒数 + + /** + * Set the current date + * + * @param date The current date in millis + */ + public void setCurrentDate(long date) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(date); + setCurrentDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), + cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); + } + + /** + * Set the current date + * + * @param year The current year + * @param month The current month + * @param dayOfMonth The current dayOfMonth + * @param hourOfDay The current hourOfDay + * @param minute The current minute + */ + public void setCurrentDate(int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + setCurrentYear(year); + setCurrentMonth(month); + setCurrentDay(dayOfMonth); + setCurrentHour(hourOfDay); + setCurrentMinute(minute); + } + + /** + * Get current year + * + * @return The current year + */ + public int getCurrentYear() { + return mDate.get(Calendar.YEAR); + } + + /** + * Set current year + * + * @param year The current year + */ + public void setCurrentYear(int year) { + if (!mInitialising && year == getCurrentYear()) { + return; + } + mDate.set(Calendar.YEAR, year); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current month in the year + * + * @return The current month in the year + */ + public int getCurrentMonth() { + return mDate.get(Calendar.MONTH); + } + + /** + * Set current month in the year + * + * @param month The month in the year + */ + public void setCurrentMonth(int month) { + if (!mInitialising && month == getCurrentMonth()) { + return; + } + mDate.set(Calendar.MONTH, month); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current day of the month + * + * @return The day of the month + */ + public int getCurrentDay() { + return mDate.get(Calendar.DAY_OF_MONTH); + } + + /** + * Set current day of the month + * + * @param dayOfMonth The day of the month + */ + public void setCurrentDay(int dayOfMonth) { + if (!mInitialising && dayOfMonth == getCurrentDay()) { + return; + } + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + updateDateControl(); + onDateTimeChanged(); + } + + /** + * Get current hour in 24 hour mode, in the range (0~23) + * @return The current hour in 24 hour mode + */ + public int getCurrentHourOfDay() { + return mDate.get(Calendar.HOUR_OF_DAY); + } + + private int getCurrentHour() { + if (mIs24HourView){ + return getCurrentHourOfDay(); + } else { + int hour = getCurrentHourOfDay(); + if (hour > HOURS_IN_HALF_DAY) { + return hour - HOURS_IN_HALF_DAY; + } else { + return hour == 0 ? HOURS_IN_HALF_DAY : hour; + } + } + } + + /** + * Set current hour in 24 hour mode, in the range (0~23) + * + * @param hourOfDay + */ + public void setCurrentHour(int hourOfDay) { + if (!mInitialising && hourOfDay == getCurrentHourOfDay()) { + return; + } + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + if (!mIs24HourView) { + if (hourOfDay >= HOURS_IN_HALF_DAY) { + mIsAm = false; + if (hourOfDay > HOURS_IN_HALF_DAY) { + hourOfDay -= HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true; + if (hourOfDay == 0) { + hourOfDay = HOURS_IN_HALF_DAY; + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(hourOfDay); + onDateTimeChanged(); + } + + /** + * Get currentMinute + * + * @return The Current Minute + */ + public int getCurrentMinute() { + return mDate.get(Calendar.MINUTE); + } + + /** + * Set current minute + */ + public void setCurrentMinute(int minute) { + if (!mInitialising && minute == getCurrentMinute()) { + return; + } + mMinuteSpinner.setValue(minute); + mDate.set(Calendar.MINUTE, minute); + onDateTimeChanged(); + } + + /** + * @return true if this is in 24 hour view else false. + */ + public boolean is24HourView () { + return mIs24HourView; + } + + /** + * Set whether in 24 hour or AM/PM mode. + * + * @param is24HourView True for 24 hour mode. False for AM/PM mode. + */ + public void set24HourView(boolean is24HourView) { + if (mIs24HourView == is24HourView) { + return; + } + mIs24HourView = is24HourView; + mAmPmSpinner.setVisibility(is24HourView ? View.GONE : View.VISIBLE); + int hour = getCurrentHourOfDay(); + updateHourControl(); + setCurrentHour(hour); + updateAmPmControl(); + } + /** + * 几个辅助方法,用于更新日期、上午/下午选择和小时选择控件的显示和属性 + * 这些方法的作用是在选择器控件显示之前或用户改变了日期、时间模式时,更新相应控件的显示和属性,以保持界面的正确性和一致性 + */ + private void updateDateControl() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(mDate.getTimeInMillis()); + cal.add(Calendar.DAY_OF_YEAR, -DAYS_IN_ALL_WEEK / 2 - 1); + mDateSpinner.setDisplayedValues(null); + for (int i = 0; i < DAYS_IN_ALL_WEEK; ++i) { + cal.add(Calendar.DAY_OF_YEAR, 1); + mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); + } + mDateSpinner.setDisplayedValues(mDateDisplayValues); + mDateSpinner.setValue(DAYS_IN_ALL_WEEK / 2); + mDateSpinner.invalidate(); + } + + private void updateAmPmControl() { + if (mIs24HourView) { + mAmPmSpinner.setVisibility(View.GONE); + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM; + mAmPmSpinner.setValue(index); + mAmPmSpinner.setVisibility(View.VISIBLE); + } + } + + private void updateHourControl() { + if (mIs24HourView) { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_24_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_24_HOUR_VIEW); + } else { + mHourSpinner.setMinValue(HOUR_SPINNER_MIN_VAL_12_HOUR_VIEW); + mHourSpinner.setMaxValue(HOUR_SPINNER_MAX_VAL_12_HOUR_VIEW); + } + } + + /** + * Set the callback that indicates the 'Set' button has been pressed. + * @param callback the callback, if null will do nothing + */ + public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { + mOnDateTimeChangedListener = callback; + } + + private void onDateTimeChanged() { + if (mOnDateTimeChangedListener != null) { + mOnDateTimeChangedListener.onDateTimeChanged(this, getCurrentYear(), + getCurrentMonth(), getCurrentDay(), getCurrentHourOfDay(), getCurrentMinute()); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java b/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java new file mode 100644 index 0000000..52640a8 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/DateTimePickerDialog.java @@ -0,0 +1,126 @@ +package net.micode.notes.ui; + +import java.util.Calendar; + +import net.micode.notes.R; +import net.micode.notes.ui.DateTimePicker; +import net.micode.notes.ui.DateTimePicker.OnDateTimeChangedListener; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.text.format.DateFormat; +import android.text.format.DateUtils; +/** + * @Package: net.micode.notes.ui + * @ClassName: DateTimePickerDialog + * @Description: + * DateTimePickerDialog是一个自定义对话框,允许用户选择日期和时间。 + * 它继承自AlertDialog类,并实现OnClickListener接口。 + * 对话框包含一个DateTimePicker控件,用于选择日期和时间。 + * 通过OnDateTimeSetListener接口将选择的日期和时间传递给监听器。 + * 对话框还提供了设置24小时制和使用选择的日期更新对话框标题的方法。 + * onClick方法处理按钮点击事件,并在日期和时间设置完成时通知监听器。 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:32 AM + * @Version: 1.0 + */ +public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + + private Calendar mDate = Calendar.getInstance(); + private boolean mIs24HourView; + private OnDateTimeSetListener mOnDateTimeSetListener; + private DateTimePicker mDateTimePicker; + + /** + * 用于接收用户设置的日期和时间的接口。 + */ + public interface OnDateTimeSetListener { + void OnDateTimeSet(AlertDialog dialog, long date); + } + + /** + * @method DateTimePickerDialog + * @description + * 构造一个新的DateTimePickerDialog + * Remind me功能的对话框 + * @date: 12/21/2023 8:01 AM + * @author: YangYizhe + * @param context 上下文环境。 + * @param date 要在对话框中显示的初始日期。 + */ + public DateTimePickerDialog(Context context, long date) { + super(context); + mDateTimePicker = new DateTimePicker(context); + setView(mDateTimePicker); + + mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { + public void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + mDate.set(Calendar.YEAR, year); + mDate.set(Calendar.MONTH, month); + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + mDate.set(Calendar.MINUTE, minute); + updateTitle(mDate.getTimeInMillis()); + } + }); + + mDate.setTimeInMillis(date); + mDate.set(Calendar.SECOND, 0); + mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); + + setButton(context.getString(R.string.datetime_dialog_ok), this); + setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener) null); + + set24HourView(DateFormat.is24HourFormat(this.getContext())); + updateTitle(mDate.getTimeInMillis()); + } + + /** + * 设置对话框是否为24小时制。 + * + * @param is24HourView 如果对话框为24小时制,则为true;否则为false。 + */ + public void set24HourView(boolean is24HourView) { + mIs24HourView = is24HourView; + } + + /** + * 设置日期和时间设置监听器。 + * + * @param callBack 要通知的监听器。 + */ + public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { + mOnDateTimeSetListener = callBack; + } + + /** + * 使用指定的日期更新对话框标题。 + * + * @param date 要显示在标题中的日期。 + */ + private void updateTitle(long date) { + int flag = + DateUtils.FORMAT_SHOW_YEAR | + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; + flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR; + + setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); + } + + /** + * 处理按钮点击事件。 + * + * @param arg0 接收到点击事件的对话框。 + * @param arg1 被点击的按钮。 + */ + public void onClick(DialogInterface arg0, int arg1) { + if (mOnDateTimeSetListener != null) { + mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/DropdownMenu.java b/src/main/java/net/micode/notes/ui/DropdownMenu.java new file mode 100644 index 0000000..b437d41 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/DropdownMenu.java @@ -0,0 +1,62 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.PopupMenu; +import android.widget.PopupMenu.OnMenuItemClickListener; + +import net.micode.notes.R; +/** + * @Package: net.micode.notes.ui + * @ClassName: DropdownMenu + * @Description: + * DropdownMenu是一个自定义下拉菜单控件。 + * 它使用Button作为触发器,通过PopupMenu显示菜单选项。 + * 构造函数接收一个上下文环境、一个Button和菜单资源的ID。 + * 通过setOnDropdownMenuItemClickListener方法设置菜单选项的点击监听器。 + * 可以通过findItem方法查找特定的菜单选项。 + * 通过setTitle方法设置下拉菜单的标题 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:36 AM + * @Version: 1.0 + */ +public class DropdownMenu { + private Button mButton; + private PopupMenu mPopupMenu; + //声明一个下拉菜单 + private Menu mMenu; + + public DropdownMenu(Context context, Button button, int menuId) { + mButton = button; + mButton.setBackgroundResource(R.drawable.dropdown_icon); + //设置这个view的背景 + mPopupMenu = new PopupMenu(context, mButton); + mMenu = mPopupMenu.getMenu(); + mPopupMenu.getMenuInflater().inflate(menuId, mMenu); + //MenuInflater是用来实例化Menu目录下的Menu布局文件 + //根据ID来确认menu的内容选项 + mButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPopupMenu.show(); + } + }); + } + + public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { + if (mPopupMenu != null) { + mPopupMenu.setOnMenuItemClickListener(listener); + } + } + + public MenuItem findItem(int id) { + return mMenu.findItem(id); + }//对于菜单选项的初始化,根据索引搜索菜单需要的选项 + + public void setTitle(CharSequence title) { + mButton.setText(title); + }//布局文件,设置标题 +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/FoldersListAdapter.java b/src/main/java/net/micode/notes/ui/FoldersListAdapter.java new file mode 100644 index 0000000..8c3a217 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/FoldersListAdapter.java @@ -0,0 +1,83 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.database.Cursor; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; + +/** + * @Package: net.micode.notes.ui + * @ClassName: FoldersListAdapter + * @Description: + * FoldersListAdapter是一个用于展示便签文件夹的列表适配器。 + * 它继承了CursorAdapter类,主要负责便签数据库和用户界面的交互。 + * 通过PROJECTION数组定义了需要从数据库中获取的数据列。 + * 它通过newView方法创建文件夹视图,并通过bindView方法将布局文件和数据绑定在一起。 + * getFolderName方法可以根据位置获取对应便签文件夹的名称 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:37 AM + * @Version: 1.0 + */ +public class FoldersListAdapter extends CursorAdapter { + //CursorAdapter是Cursor和ListView的接口 + //FoldersListAdapter继承了CursorAdapter的类 + //主要作用是便签数据库和用户的交互 + //这里就是用folder(文件夹)的形式展现给用户 + public static final String [] PROJECTION = { + NoteColumns.ID, + NoteColumns.SNIPPET + };//调用数据库中便签的ID和片段 + + public static final int ID_COLUMN = 0; + public static final int NAME_COLUMN = 1; + + public FoldersListAdapter(Context context, Cursor c) { + super(context, c); + // TODO Auto-generated constructor stub + }//数据库操作 + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + //ViewGroup是容器 + return new FolderListItem(context); + }//创建一个文件夹,对于各文件夹中子标签的初始化 + + @Override + public void bindView(View view, Context context, Cursor cursor) { + if (view instanceof FolderListItem) { + String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + ((FolderListItem) view).bind(folderName); + } + }//将各个布局文件绑定起来 + + public String getFolderName(Context context, int position) { + Cursor cursor = (Cursor) getItem(position); + return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + }//根据数据库中标签的ID得到标签的各项内容 + + private class FolderListItem extends LinearLayout { + private TextView mName; + + public FolderListItem(Context context) { + super(context); + //操作数据库 + inflate(context, R.layout.folder_list_item, this); + //根据布局文件的名字等信息将其找出来 + mName = (TextView) findViewById(R.id.tv_folder_name); + } + + public void bind(String name) { + mName.setText(name); + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/NoteEditText.java b/src/main/java/net/micode/notes/ui/NoteEditText.java new file mode 100644 index 0000000..c935358 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/NoteEditText.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.Context; +import android.graphics.Rect; +import android.text.Layout; +import android.text.Selection; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.URLSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.view.ContextMenu; +import android.view.KeyEvent; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.widget.EditText; + +import net.micode.notes.R; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Package: net.micode.notes.ui + * @ClassName: NoteEditText + * @Description: + * @Author: YangYizhe + * @CreateDate: 12/21/2023 12:38 AM + * @Version: 1.0 + */ +public class NoteEditText extends EditText { + //常量标识 + private static final String TAG = "NoteEditText"; + //声明整型变量,文本索引 + private int mIndex; + //声明整型变量 + private int mSelectionStartBeforeDelete; + + //声明字符串常量,标志电话、网址、邮件 + private static final String SCHEME_TEL = "tel:" ; + private static final String SCHEME_HTTP = "http:" ; + private static final String SCHEME_EMAIL = "mailto:" ; + + //设置映射,将文本内容(电话、网址、邮件)做链接处理 + private static final Map sSchemaActionResMap = new HashMap(); + static { + sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); + sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web); + sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email); + } + + /** + * Call by the {@link NoteEditActivity} to delete or add edit text + * 该接口用于实现对TextView组件中的文字信息进行修改 + */ + public interface OnTextViewChangeListener { + /** + * Delete current edit text when {@link KeyEvent#KEYCODE_DEL} happens + * and the text is null + * 当delete键按下时删除当前编辑的文字块 + */ + void onEditTextDelete(int index, String text); + + /** + * Add edit text after current edit text when {@link KeyEvent#KEYCODE_ENTER} + * happen + * 当enter键按下时添加一个文字编辑块 + */ + void onEditTextEnter(int index, String text); + + /** + * Hide or show item option when text change + * 当文字发生变化时隐藏或者显示设置 + */ + void onTextChange(int index, boolean hasText); + } + + //声明文本视图变化监听器 + private OnTextViewChangeListener mOnTextViewChangeListener; + + /** + * 构造方法,实例化NoteEditText + */ + public NoteEditText(Context context) { + super(context, null); + mIndex = 0; + } + + //设置索引号 + public void setIndex(int index) { + mIndex = index; + } + + /** + * 设置文本视图变化监听器 + */ + public void setOnTextViewChangeListener(OnTextViewChangeListener listener) { + mOnTextViewChangeListener = listener; + } + + /** + * 构造方法,是由参数集(文本编辑风格)实例化NoteEditText + */ + public NoteEditText(Context context, AttributeSet attrs) { + super(context, attrs, android.R.attr.editTextStyle); + } + /** + * 构造方法,是由参数集(文本编辑风格、定义风格)实例化NoteEditText + */ + public NoteEditText(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + // TODO Auto-generated constructor stub + } + + /** + * @method onTouchEvent + * @description 处理触摸事件,根据触摸点的位置设置光标的位置 + * @date: 12/21/2023 12:41 AM + * @author: YangYizhe + * @param + * @return + */ + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + + int x = (int) event.getX(); + int y = (int) event.getY(); + x -= getTotalPaddingLeft(); + y -= getTotalPaddingTop(); + x += getScrollX(); + y += getScrollY(); + Layout layout = getLayout(); + int line = layout.getLineForVertical(y); + int off = layout.getOffsetForHorizontal(line, x); + Selection.setSelection(getText(), off); + break; + } + return super.onTouchEvent(event); + } + /** + * @method onKeyDown + * @description 监听键盘按键按下 + * @date: 12/21/2023 12:40 AM + * @author: YangYizhe + * @param keyCode 键盘按键的编码 + * @param event 按键事件 + * @return boolean + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_ENTER: + if (mOnTextViewChangeListener != null) { + return false; + } + break; + case KeyEvent.KEYCODE_DEL: + mSelectionStartBeforeDelete = getSelectionStart(); + break; + default: + break; + } + return super.onKeyDown(keyCode, event); + } + + /** + * @method onKeyUp + * @description 监听按键抬起 + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param keyCode + * @param event + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch(keyCode) { + case KeyEvent.KEYCODE_DEL: + if (mOnTextViewChangeListener != null) { + if (0 == mSelectionStartBeforeDelete && mIndex != 0) { + mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString()); + return true; + } + } else { + Log.d(TAG, "OnTextViewChangeListener was not seted"); + } + break; + case KeyEvent.KEYCODE_ENTER: + if (mOnTextViewChangeListener != null) { + int selectionStart = getSelectionStart(); + String text = getText().subSequence(selectionStart, length()).toString(); + setText(getText().subSequence(0, selectionStart)); + mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text); + } else { + Log.d(TAG, "OnTextViewChangeListener was not seted"); + } + break; + default: + break; + } + return super.onKeyUp(keyCode, event); + } + + /** + * @method onFocusChanged + * @description 处理当前视图下的焦点改变事件 + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param focused 代表获得或失去焦点 + * @param direction + * @param previouslyFocusedRect 上一个访问的焦点区域 + */ + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + if (mOnTextViewChangeListener != null) { + if (!focused && TextUtils.isEmpty(getText())) { + mOnTextViewChangeListener.onTextChange(mIndex, false); + } else { + mOnTextViewChangeListener.onTextChange(mIndex, true); + } + } + super.onFocusChanged(focused, direction, previouslyFocusedRect); + } + + /** + * @method onCreateContextMenu + * @description + * @date: 12/21/2023 12:39 AM + * @author: YangYizhe + * @param + * @return + */ + @Override + protected void onCreateContextMenu(ContextMenu menu) { + if (getText() instanceof Spanned) { + int selStart = getSelectionStart(); + int selEnd = getSelectionEnd(); + + int min = Math.min(selStart, selEnd); + int max = Math.max(selStart, selEnd); + + final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); + if (urls.length == 1) { + int defaultResId = 0; + for(String schema: sSchemaActionResMap.keySet()) { + if(urls[0].getURL().indexOf(schema) >= 0) { + defaultResId = sSchemaActionResMap.get(schema); + break; + } + } + + if (defaultResId == 0) { + defaultResId = R.string.note_link_other; + } + menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener( + new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + // goto a new intent + urls[0].onClick(NoteEditText.this); + return true; + } + }); + } + } + super.onCreateContextMenu(menu); + } +} diff --git a/src/main/java/net/micode/notes/ui/NoteItemData.java b/src/main/java/net/micode/notes/ui/NoteItemData.java new file mode 100644 index 0000000..0f5a878 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/NoteItemData.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.ui; + +import android.content.Context; +import android.database.Cursor; +import android.text.TextUtils; + +import net.micode.notes.data.Contact; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.tool.DataUtils; + + +public class NoteItemData { + static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.ALERTED_DATE, + NoteColumns.BG_COLOR_ID, + NoteColumns.CREATED_DATE, + NoteColumns.HAS_ATTACHMENT, + NoteColumns.MODIFIED_DATE, + NoteColumns.NOTES_COUNT, + NoteColumns.PARENT_ID, + NoteColumns.SNIPPET, + NoteColumns.TYPE, + NoteColumns.WIDGET_ID, + NoteColumns.WIDGET_TYPE, + }; + + private static final int ID_COLUMN = 0; + private static final int ALERTED_DATE_COLUMN = 1; + private static final int BG_COLOR_ID_COLUMN = 2; + private static final int CREATED_DATE_COLUMN = 3; + private static final int HAS_ATTACHMENT_COLUMN = 4; + private static final int MODIFIED_DATE_COLUMN = 5; + private static final int NOTES_COUNT_COLUMN = 6; + private static final int PARENT_ID_COLUMN = 7; + private static final int SNIPPET_COLUMN = 8; + private static final int TYPE_COLUMN = 9; + private static final int WIDGET_ID_COLUMN = 10; + private static final int WIDGET_TYPE_COLUMN = 11; + + private long mId; + private long mAlertDate; + private int mBgColorId; + private long mCreatedDate; + private boolean mHasAttachment; + private long mModifiedDate; + private int mNotesCount; + private long mParentId; + private String mSnippet; + private int mType; + private int mWidgetId; + private int mWidgetType; + private String mName; + private String mPhoneNumber; + + private boolean mIsLastItem; + private boolean mIsFirstItem; + private boolean mIsOnlyOneItem; + private boolean mIsOneNoteFollowingFolder; + private boolean mIsMultiNotesFollowingFolder; + + public NoteItemData(Context context, Cursor cursor) { + mId = cursor.getLong(ID_COLUMN); + mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN); + mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN); + mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN); + mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false; + mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN); + mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN); + mParentId = cursor.getLong(PARENT_ID_COLUMN); + mSnippet = cursor.getString(SNIPPET_COLUMN); + mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace( + NoteEditActivity.TAG_UNCHECKED, ""); + mType = cursor.getInt(TYPE_COLUMN); + mWidgetId = cursor.getInt(WIDGET_ID_COLUMN); + mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN); + + mPhoneNumber = ""; + if (mParentId == Notes.ID_CALL_RECORD_FOLDER) { + mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId); + if (!TextUtils.isEmpty(mPhoneNumber)) { + mName = Contact.getContact(context, mPhoneNumber); + if (mName == null) { + mName = mPhoneNumber; + } + } + } + + if (mName == null) { + mName = ""; + } + checkPostion(cursor); + } + + private void checkPostion(Cursor cursor) { + mIsLastItem = cursor.isLast() ? true : false; + mIsFirstItem = cursor.isFirst() ? true : false; + mIsOnlyOneItem = (cursor.getCount() == 1); + mIsMultiNotesFollowingFolder = false; + mIsOneNoteFollowingFolder = false; + + if (mType == Notes.TYPE_NOTE && !mIsFirstItem) { + int position = cursor.getPosition(); + if (cursor.moveToPrevious()) { + if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER + || cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) { + if (cursor.getCount() > (position + 1)) { + mIsMultiNotesFollowingFolder = true; + } else { + mIsOneNoteFollowingFolder = true; + } + } + if (!cursor.moveToNext()) { + throw new IllegalStateException("cursor move to previous but can't move back"); + } + } + } + } + + public boolean isOneFollowingFolder() { + return mIsOneNoteFollowingFolder; + } + + public boolean isMultiFollowingFolder() { + return mIsMultiNotesFollowingFolder; + } + + public boolean isLast() { + return mIsLastItem; + } + + public String getCallName() { + return mName; + } + + public boolean isFirst() { + return mIsFirstItem; + } + + public boolean isSingle() { + return mIsOnlyOneItem; + } + + public long getId() { + return mId; + } + + public long getAlertDate() { + return mAlertDate; + } + + public long getCreatedDate() { + return mCreatedDate; + } + + public boolean hasAttachment() { + return mHasAttachment; + } + + public long getModifiedDate() { + return mModifiedDate; + } + + public int getBgColorId() { + return mBgColorId; + } + + public long getParentId() { + return mParentId; + } + + public int getNotesCount() { + return mNotesCount; + } + + public long getFolderId () { + return mParentId; + } + + public int getType() { + return mType; + } + + public int getWidgetType() { + return mWidgetType; + } + + public int getWidgetId() { + return mWidgetId; + } + + public String getSnippet() { + return mSnippet; + } + + public boolean hasAlert() { + return (mAlertDate > 0); + } + + public boolean isCallRecord() { + return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber)); + } + + public static int getNoteType(Cursor cursor) { + return cursor.getInt(TYPE_COLUMN); + } +} diff --git a/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/main/java/net/micode/notes/ui/NotesListActivity.java new file mode 100644 index 0000000..2b0e901 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -0,0 +1,1103 @@ +package net.micode.notes.ui; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.appwidget.AppWidgetManager; +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.ActionMode; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Display; +import android.view.HapticFeedbackConstants; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnCreateContextMenuListener; +import android.view.View.OnTouchListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.PopupMenu; +import android.widget.TextView; +import android.widget.Toast; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.remote.GTaskSyncService; +import net.micode.notes.model.WorkingNote; +import net.micode.notes.tool.BackupUtils; +import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; +import net.micode.notes.widget.NoteWidgetProvider_2x; +import net.micode.notes.widget.NoteWidgetProvider_4x; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashSet; +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesListActivity + * @Description: + * 小米便签的主入口,提供了一系列便签操作主要功能 + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/20 23:02 + * @Version: 1.0 + */ +public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener { + + private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; + + private static final int FOLDER_LIST_QUERY_TOKEN = 1; + + private static final int MENU_FOLDER_DELETE = 0; + + private static final int MENU_FOLDER_VIEW = 1; + + private static final int MENU_FOLDER_CHANGE_NAME = 2; + + private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; + + private enum ListEditState { + NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER + }; + + private ListEditState mState; + + private BackgroundQueryHandler mBackgroundQueryHandler; + + private NotesListAdapter mNotesListAdapter; + + private ListView mNotesListView; + + private Button mAddNewNote; + + private boolean mDispatch; + + private int mOriginY; + + private int mDispatchY; + + private TextView mTitleBar; + + private long mCurrentFolderId; + + private ContentResolver mContentResolver; + + private ModeCallback mModeCallBack; + + private static final String TAG = "NotesListActivity"; + + public static final int NOTES_LISTVIEW_SCROLL_RATE = 30; + + private NoteItemData mFocusNoteDataItem; + + private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?"; + + private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR (" + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + + NoteColumns.NOTES_COUNT + ">0)"; + + private final static int REQUEST_CODE_OPEN_NODE = 102; + private final static int REQUEST_CODE_NEW_NODE = 103; + @Override + /** + * @method onCreate + * @description: + * @date: 2023/12/21 1:52 + * @author: WUSHUXIAN + * @param void + * @return void + */ + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); // 调用父类的onCreate函数 + setContentView(R.layout.note_list); + initResources(); + setAppInfoFromRawRes(); + } + + @Override + /** + * @method onActivityResult + * @description: + * 参数: + * requestCode: + * resultCode: + * data; + * @date: 2023/12/20 23:26 + * @author: WUSHUXIAN + * @param void + * @return void + */ + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (resultCode == RESULT_OK + && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) { + mNotesListAdapter.changeCursor(null); + } else { + super.onActivityResult(requestCode, resultCode, data);// 调用 Activity 的onActivityResult() + } + } + /** + * @method setAppInfoFromRawRes + * @description: + * @date: 2023/12/20 23:24 + * @author: WUSHUXIAN + * @param + * @return + */ + private void setAppInfoFromRawRes() { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);// Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。 + if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) { + StringBuilder sb = new StringBuilder(); + InputStream in = null; + try { + in = getResources().openRawResource(R.raw.introduction); + if (in != null) { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + char [] buf = new char[1024]; + int len = 0; + while ((len = br.read(buf)) > 0) { + sb.append(buf, 0, len); + } + } else { + Log.e(TAG, "Read introduction file error"); + return; + } + } catch (IOException e) { + e.printStackTrace(); + return; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + // 创建空的WorkingNote + WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER, + AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE, + ResourceParser.RED); + note.setWorkingText(sb.toString()); + if (note.saveNote()) { + // 更新保存note的信息 + sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); + } else { + Log.e(TAG, "Save introduction note error"); + return; + } + } + } + + @Override + protected void onStart() { + super.onStart(); + startAsyncNotesListQuery(); + } + /** + * @method initResources + * @description 初始化资源 + * @date: 2023/12/20 23:09 + * @author: WUSHUXIAN + * @param + * @return + */ + private void initResources() { + mContentResolver = this.getContentResolver(); // 获取应用程序的数据,得到类似数据表的东西 + mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver()); + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + + // findViewById 是安卓编程的定位函数,主要是引用.R文件里的引用名 + mNotesListView = (ListView) findViewById(R.id.notes_list); // 绑定XML中的ListView,作为Item的容器 + mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null), + null, false); + mNotesListView.setOnItemClickListener(new OnListItemClickListener()); + mNotesListView.setOnItemLongClickListener(this); + mNotesListAdapter = new NotesListAdapter(this); + mNotesListView.setAdapter(mNotesListAdapter); + mAddNewNote = (Button) findViewById(R.id.btn_new_note);// 在activity中要获取该按钮 + mAddNewNote.setOnClickListener(this); + mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener()); + mDispatch = false; + mDispatchY = 0; + mOriginY = 0; + mTitleBar = (TextView) findViewById(R.id.tv_title_bar); + mState = ListEditState.NOTE_LIST; + mModeCallBack = new ModeCallback(); + } + + // + /** + * @Package: net.micode.notes.ui + * @ClassName: ModeCallback + * @Description: 继承自ListView.MultiChoiceModeListener 和 OnMenuItemClickListener + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/20 23:37 + * @Version: 1.0 + */ + private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener { + private DropdownMenu mDropDownMenu; + private ActionMode mActionMode; + private MenuItem mMoveMenu; + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + getMenuInflater().inflate(R.menu.note_list_options, menu); + menu.findItem(R.id.delete).setOnMenuItemClickListener(this); + mMoveMenu = menu.findItem(R.id.move); + if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER + || DataUtils.getUserFolderCount(mContentResolver) == 0) { + mMoveMenu.setVisible(false); + } else { + mMoveMenu.setVisible(true); + mMoveMenu.setOnMenuItemClickListener(this); + } + mActionMode = mode; + mNotesListAdapter.setChoiceMode(true); + mNotesListView.setLongClickable(false); + mAddNewNote.setVisibility(View.GONE); + + View customView = LayoutInflater.from(NotesListActivity.this).inflate( + R.layout.note_list_dropdown_menu, null); + mode.setCustomView(customView); + mDropDownMenu = new DropdownMenu(NotesListActivity.this, + (Button) customView.findViewById(R.id.selection_menu), + R.menu.note_list_dropdown); + mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){ + public boolean onMenuItemClick(final MenuItem item) { + mNotesListAdapter.selectAll(!mNotesListAdapter.isAllSelected()); + updateMenu(); + return true; + } + + }); + return true; + } + /** + * @method updateMenu + * @description 更新菜单 + * @date: 2023/12/16 23:36 + * @author: WUSHUXIAN + * @param + * @return + */ + private void updateMenu() { + int selectedCount = mNotesListAdapter.getSelectedCount(); + // Update dropdown menu + String format = getResources().getString(R.string.menu_select_title, selectedCount); + mDropDownMenu.setTitle(format); // 更改标题 + MenuItem item = mDropDownMenu.findItem(R.id.action_select_all); + if (item != null) { + if (mNotesListAdapter.isAllSelected()) { + item.setChecked(true); + item.setTitle(R.string.menu_deselect_all); + } else { + item.setChecked(false); + item.setTitle(R.string.menu_select_all); + } + } + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + // TODO Auto-generated method stub + return false; + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + // TODO Auto-generated method stub + return false; + } + + public void onDestroyActionMode(ActionMode mode) { + mNotesListAdapter.setChoiceMode(false); + mNotesListView.setLongClickable(true); + mAddNewNote.setVisibility(View.VISIBLE); + } + + public void finishActionMode() { + mActionMode.finish(); + } + + public void onItemCheckedStateChanged(ActionMode mode, int position, long id, + boolean checked) { + mNotesListAdapter.setCheckedItem(position, checked); + updateMenu(); + } + /** + * @method onMenuItemClick + * @description: + * @date: 2023/12/20 23:39 + * @author: WUSHUXIAN + * @param + * @return + */ + public boolean onMenuItemClick(MenuItem item) { + if (mNotesListAdapter.getSelectedCount() == 0) { + Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none), + Toast.LENGTH_SHORT).show(); + return true; + } + + int itemId = item.getItemId(); + if (itemId == R.id.delete) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_notes, + mNotesListAdapter.getSelectedCount())); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + batchDelete(); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + } else if (itemId == R.id.move) { + startQueryDestinationFolders(); + } else { + return false; + } + return true; + } + } + //接口的实现 + private class NewNoteOnTouchListener implements OnTouchListener { + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + Display display = getWindowManager().getDefaultDisplay(); + int screenHeight = display.getHeight(); + int newNoteViewHeight = mAddNewNote.getHeight(); + int start = screenHeight - newNoteViewHeight; + int eventY = start + (int) event.getY(); + /** + * Minus TitleBar's height + */ + if (mState == ListEditState.SUB_FOLDER) { + eventY -= mTitleBar.getHeight(); + start -= mTitleBar.getHeight(); + } + /** + * HACKME:When click the transparent part of "New Note" button, dispatch + * the event to the list view behind this button. The transparent part of + * "New Note" button could be expressed by formula y=-0.12x+94锛圲nit:pixel锛� + * and the line top of the button. The coordinate based on left of the "New + * Note" button. The 94 represents maximum height of the transparent part. + * Notice that, if the background of the button changes, the formula should + * also change. This is very bad, just for the UI designer's strong requirement. + */ + if (event.getY() < (event.getX() * (-0.12) + 94)) { + View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1 + - mNotesListView.getFooterViewsCount()); + if (view != null && view.getBottom() > start + && (view.getTop() < (start + 94))) { + mOriginY = (int) event.getY(); + mDispatchY = eventY; + event.setLocation(event.getX(), mDispatchY); + mDispatch = true; + return mNotesListView.dispatchTouchEvent(event); + } + } + break; + } + case MotionEvent.ACTION_MOVE: { + if (mDispatch) { + mDispatchY += (int) event.getY() - mOriginY; + event.setLocation(event.getX(), mDispatchY); + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + default: { + if (mDispatch) { + event.setLocation(event.getX(), mDispatchY); + mDispatch = false; + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + } + return false; + } + + }; + /** + * @method startAsyncNotesListQuery + * @description: 启动异步Notes列表查询 + * @date: 2023/12/20 23:45 + * @author: WUSHUXIAN + * @param + * @return + */ + private void startAsyncNotesListQuery() { + String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION : NORMAL_SELECTION; + mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null, + Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] {String.valueOf(mCurrentFolderId)}, + NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC"); + } + /** + * @Package: net.micode.notes.ui + * @ClassName: BackgroundQueryHandler + * @Description: 对AsyncQueryHandler的拓展,背景查询处理 + * @Author: WUSHUXIAN + * @CreateDate: 2023/12/21 0:01 + * @Version: 1.0 + */ + private final class BackgroundQueryHandler extends AsyncQueryHandler { + public BackgroundQueryHandler(ContentResolver contentResolver) { + super(contentResolver); + } + + @Override + /** + * @method onQueryComplete + * @description: 在异步查询完成时调用。 + * @date: 2023/12/20 23:56 + * @author: WUSHUXIAN + * @param token 标识查询的令牌 + * @param cookie 传入的cookie对象 + * @param cursor 保存查询结果的光标 + * @return void + */ + protected void onQueryComplete(int token, Object cookie, Cursor cursor) { + switch (token) { + case FOLDER_NOTE_LIST_QUERY_TOKEN: + mNotesListAdapter.changeCursor(cursor); + break; + case FOLDER_LIST_QUERY_TOKEN: + if (cursor != null && cursor.getCount() > 0) { + showFolderListMenu(cursor); + } else { + Log.e(TAG, "Query folder failed"); + } + break; + default: + return; + } + } + } + + private void showFolderListMenu(Cursor cursor) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(R.string.menu_title_select_folder); + final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + DataUtils.batchMoveToFolder(mContentResolver, + mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which)); + Toast.makeText( + NotesListActivity.this, + getString(R.string.format_move_notes_to_folder, + mNotesListAdapter.getSelectedCount(), + adapter.getFolderName(NotesListActivity.this, which)), + Toast.LENGTH_SHORT).show(); + mModeCallBack.finishActionMode(); + } + }); + builder.show(); + } + /** + * @method createNewNote + * @description 创建便签 + * @date: 12/21/2023 1:58 AM + * @author: YangYizhe + * @param + * @return + */ + private void createNewNote() { + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId); + this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE); + } + /** + * @method batchDelete + * @description: + * 删除便签操作 + * @date: 2023/12/21 0:14 + * @author: WUSHUXIAN + * @param + * @return void + */ + @SuppressLint("StaticFieldLeak") + private void batchDelete() { + new AsyncTask>() { + protected HashSet doInBackground(Void... unused) { + HashSet widgets = mNotesListAdapter.getSelectedWidget(); + //如果没有同步,直接删除 + if (!isSyncMode()) { + if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter + .getSelectedItemIds())) { + } else { + Log.e(TAG, "Delete notes error, should not happens"); + } + } + //已同步,将删除的便签移到垃圾桶 + else { + if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter + .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) { + Log.e(TAG, "Move notes to trash folder error, should not happens"); + } + } + return widgets; + } + + @Override + protected void onPostExecute(HashSet widgets) { + if (widgets != null) { + for (AppWidgetAttribute widget : widgets) { + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + mModeCallBack.finishActionMode(); + } + }.execute(); + } + /** + * @method deleteFolder + * @description: 删除文件夹 + * @date: 2023/12/21 0:32 + * @author: WUSHUXIAN + * @param folderId 文件标识 + * @return void + */ + private void deleteFolder(long folderId) { + if (folderId == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Wrong folder id, should not happen " + folderId); + return; + } + + HashSet ids = new HashSet(); + ids.add(folderId); + HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, + folderId); + if (!isSyncMode()) { + // if not synced, delete folder directly + DataUtils.batchDeleteNotes(mContentResolver, ids); + } else { + // in sync mode, we'll move the deleted folder into the trash folder + DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER); + } + if (widgets != null) { + for (AppWidgetAttribute widget : widgets) { + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + } + + /** + * @method openNode + * @description + * 打开便签的功能 + * @date: 12/21/2023 8:05 AM + * @author: YangYizhe + * @param data + */ + private void openNode(NoteItemData data) { + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, data.getId()); + this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + } + /** + * @method openFolder + * @description 打开文件夹功能 + * @date: 12/21/2023 8:05 AM + * @author: YangYizhe + * @param data + */ + private void openFolder(NoteItemData data) { + mCurrentFolderId = data.getId(); + startAsyncNotesListQuery(); + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mState = ListEditState.CALL_RECORD_FOLDER; + mAddNewNote.setVisibility(View.GONE); + } else { + mState = ListEditState.SUB_FOLDER; + } + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mTitleBar.setText(R.string.call_record_folder_name); + } else { + mTitleBar.setText(data.getSnippet()); + } + mTitleBar.setVisibility(View.VISIBLE); + } + /** + * @method onClick + * @description 如果碰到写便签按钮,新建便签 + * @date: 12/21/2023 8:06 AM + * @author: YangYizhe + * @param + */ + public void onClick(View v) { + if (v.getId() == R.id.btn_new_note) { + createNewNote(); + } + } + + private void showSoftInput() { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + private void hideSoftInput(View view) { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + /** + * @method showCreateOrModifyFolderDialog + * @description: 创建或者修改文件夹时显示对话框 + * @date: 2023/12/21 0:39 + * @author: WUSHUXIAN + * @param create + * @return void + */ + private void showCreateOrModifyFolderDialog(final boolean create) { + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null); + final EditText etName = (EditText) view.findViewById(R.id.et_foler_name); + showSoftInput(); + if (!create) { + if (mFocusNoteDataItem != null) { + etName.setText(mFocusNoteDataItem.getSnippet()); + builder.setTitle(getString(R.string.menu_folder_change_name)); + } else { + Log.e(TAG, "The long click data item is null"); + return; + } + } else { + etName.setText(""); + builder.setTitle(this.getString(R.string.menu_create_folder)); + } + + builder.setPositiveButton(android.R.string.ok, null); + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + hideSoftInput(etName); + } + }); + + final Dialog dialog = builder.setView(view).show(); + final Button positive = (Button)dialog.findViewById(android.R.id.button1); + positive.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + hideSoftInput(etName); + String name = etName.getText().toString(); + if (DataUtils.checkVisibleFolderName(mContentResolver, name)) { + Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name), + Toast.LENGTH_LONG).show(); + etName.setSelection(0, etName.length()); + return; + } + if (!create) { + if (!TextUtils.isEmpty(name)) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID + + "=?", new String[] { + String.valueOf(mFocusNoteDataItem.getId()) + }); + } + } else if (!TextUtils.isEmpty(name)) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + mContentResolver.insert(Notes.CONTENT_NOTE_URI, values); + } + dialog.dismiss(); + } + }); + //如果便签名是空的,则禁用确认按钮 + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } + etName.addTextChangedListener(new TextWatcher() { + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // TODO Auto-generated method stub + + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } else { + positive.setEnabled(true); + } + } + + public void afterTextChanged(Editable s) { + // TODO Auto-generated method stub + + } + }); + } + + /* (non-Javadoc) + * @see android.app.Activity#onBackPressed() + * 按返回键时根据情况更改类中的数据 + */ + @Override + public void onBackPressed() { + switch (mState) { + case SUB_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + startAsyncNotesListQuery(); + mTitleBar.setVisibility(View.GONE); + break; + case CALL_RECORD_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + mAddNewNote.setVisibility(View.VISIBLE); + mTitleBar.setVisibility(View.GONE); + startAsyncNotesListQuery(); + break; + case NOTE_LIST: + super.onBackPressed(); + break; + default: + break; + } + } + + /** + * @param appWidgetId + * @param appWidgetType + * 根据不同类型的widget更新插件,通过intent传送数据 + */ + private void updateWidget(int appWidgetId, int appWidgetType) { + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + if (appWidgetType == Notes.TYPE_WIDGET_2X) { + intent.setClass(this, NoteWidgetProvider_2x.class); + } else if (appWidgetType == Notes.TYPE_WIDGET_4X) { + intent.setClass(this, NoteWidgetProvider_4x.class); + } else { + Log.e(TAG, "Unspported widget type"); + return; + } + + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { + appWidgetId + }); + + sendBroadcast(intent); + setResult(RESULT_OK, intent); + } + /** + * @method OnCreateContextMenuListener + * @description: 生成便签初始界面 + * @date: 2023/12/21 1:16 + * @author: WUSHUXIAN + */ + private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() { + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + if (mFocusNoteDataItem != null) { + menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); + menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view); + menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); + menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name); + } + } + }; + + @Override + public void onContextMenuClosed(Menu menu) { + if (mNotesListView != null) { + mNotesListView.setOnCreateContextMenuListener(null); + } + super.onContextMenuClosed(menu); + } + + /* (non-Javadoc) + * @see android.app.Activity#onContextItemSelected(android.view.MenuItem) + * 针对menu中不同的选择进行不同的处理,里面详细注释 + */ + @Override + public boolean onContextItemSelected(MenuItem item) { + if (mFocusNoteDataItem == null) { + Log.e(TAG, "The long click data item is null"); + return false; + } + switch (item.getItemId()) { + case MENU_FOLDER_VIEW: + openFolder(mFocusNoteDataItem);//打开对应文件 + break; + case MENU_FOLDER_DELETE: + AlertDialog.Builder builder = new AlertDialog.Builder(this);//设置确认是否删除的对话框 + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_folder)); + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + deleteFolder(mFocusNoteDataItem.getId()); + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show();//显示对话框 + break; + case MENU_FOLDER_CHANGE_NAME: + showCreateOrModifyFolderDialog(false); + break; + default: + break; + } + + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.clear(); + if (mState == ListEditState.NOTE_LIST) { + getMenuInflater().inflate(R.menu.note_list, menu); + // set sync or sync_cancel + menu.findItem(R.id.menu_sync).setTitle( + GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync); + } else if (mState == ListEditState.SUB_FOLDER) { + getMenuInflater().inflate(R.menu.sub_folder, menu); + } else if (mState == ListEditState.CALL_RECORD_FOLDER) { + getMenuInflater().inflate(R.menu.call_record_folder, menu); + } else { + Log.e(TAG, "Wrong state:" + mState); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + if (itemId == R.id.menu_new_folder) { + showCreateOrModifyFolderDialog(true); + } else if (itemId == R.id.menu_export_text) { + exportNoteToText(); + } else if (itemId == R.id.menu_sync) { + if (isSyncMode()) { + if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) { + GTaskSyncService.startSync(this); + } else { + GTaskSyncService.cancelSync(this); + } + } else { + startPreferenceActivity(); + } + } else if (itemId == R.id.menu_setting) { + startPreferenceActivity(); + } else if (itemId == R.id.menu_new_note) { + createNewNote(); + } else if (itemId == R.id.menu_search) { + onSearchRequested(); + } + return true; + } + + /* (non-Javadoc) + * @see android.app.Activity#onSearchRequested() + * 直接调用startSearch函数 + */ + @Override + public boolean onSearchRequested() { + startSearch(null, false, null /* appData */, false); + return true; + } + + /** + * @method exportNoteToText + * @description 将便签导出,export text按钮 + * @date: 12/21/2023 8:08 AM + * @author: YangYizhe + */ + private void exportNoteToText() { + final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this); + new AsyncTask() { + + @Override + protected Integer doInBackground(Void... unused) { + return backup.exportToText(); + } + + @Override + protected void onPostExecute(Integer result) { + if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_unmounted)); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } else if (result == BackupUtils.STATE_SUCCESS) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.success_sdcard_export)); + builder.setMessage(NotesListActivity.this.getString( + R.string.format_exported_file_location, backup + .getExportedTextFileName(), backup.getExportedTextFileDir())); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } else if (result == BackupUtils.STATE_SYSTEM_ERROR) { + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_export)); + builder.setPositiveButton(android.R.string.ok, null); + builder.show(); + } + } + + }.execute(); + } + + + private boolean isSyncMode() { + return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; + } + + private void startPreferenceActivity() { + Activity from = getParent() != null ? getParent() : this; + Intent intent = new Intent(from, NotesPreferenceActivity.class); + from.startActivityIfNeeded(intent, -1); + } + + /** + * @Package: net.micode.notes.ui + * @ClassName: NotesListActivity + * @Description: 响应了按钮的点击 + * @Author: YangYizhe + * @CreateDate: 12/21/2023 8:09 AM + * @Version: 1.0 + */ + private class OnListItemClickListener implements OnItemClickListener { + + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (view instanceof NotesListItem) { + NoteItemData item = ((NotesListItem) view).getItemData(); + if (mNotesListAdapter.isInChoiceMode()) { + if (item.getType() == Notes.TYPE_NOTE) { + position = position - mNotesListView.getHeaderViewsCount(); + mModeCallBack.onItemCheckedStateChanged(null, position, id, + !mNotesListAdapter.isSelectedItem(position)); + } + return; + } + + switch (mState) { + case NOTE_LIST: + if (item.getType() == Notes.TYPE_FOLDER + || item.getType() == Notes.TYPE_SYSTEM) { + openFolder(item); + } else if (item.getType() == Notes.TYPE_NOTE) { + openNode(item); + } else { + Log.e(TAG, "Wrong note type in NOTE_LIST"); + } + break; + case SUB_FOLDER: + case CALL_RECORD_FOLDER: + if (item.getType() == Notes.TYPE_NOTE) { + openNode(item); + } else { + Log.e(TAG, "Wrong note type in SUB_FOLDER"); + } + break; + default: + break; + } + } + } + + } + + /** + * 查询目标文件 + */ + private void startQueryDestinationFolders() { + String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?"; + selection = (mState == ListEditState.NOTE_LIST) ? selection: + "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")"; + + mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN, + null, + Notes.CONTENT_NOTE_URI, + FoldersListAdapter.PROJECTION, + selection, + new String[] { + String.valueOf(Notes.TYPE_FOLDER), + String.valueOf(Notes.ID_TRASH_FOLER), + String.valueOf(mCurrentFolderId) + }, + NoteColumns.MODIFIED_DATE + " DESC"); + } + + /** + * @method onItemLongClick + * @description + * 长按某一项时进行的操作 + * 如果长按的是便签,则通过ActionMode菜单实现;如果长按的是文件夹,则通过ContextMenu菜单实现; + * @date: 12/21/2023 8:10 AM + * @author: YangYizhe + * @param + * @return + */ + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + if (view instanceof NotesListItem) { + mFocusNoteDataItem = ((NotesListItem) view).getItemData(); + if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) { + if (mNotesListView.startActionMode(mModeCallBack) != null) { + mModeCallBack.onItemCheckedStateChanged(null, position, id, true); + mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } else { + Log.e(TAG, "startActionMode fails"); + } + } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) { + mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener); + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/main/java/net/micode/notes/ui/NotesListItem.java new file mode 100644 index 0000000..d32a37b --- /dev/null +++ b/src/main/java/net/micode/notes/ui/NotesListItem.java @@ -0,0 +1,123 @@ +package net.micode.notes.ui; + +import android.content.Context; +import android.text.format.DateUtils; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.ResourceParser.NoteItemBgResources; + + +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesListItem + * @Description: + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:35 PM + * @Version: 1.0 + */ +public class NotesListItem extends LinearLayout { + private ImageView mAlert;//闹钟图片 + private TextView mTitle; //标题 + private TextView mTime; //时间 + private TextView mCallName; // + private NoteItemData mItemData; //标签数据 + private CheckBox mCheckBox; //打钩框 + + /*初始化基本信息*/ + public NotesListItem(Context context) { + super(context); //super()它的主要作用是调整调用父类构造函数的顺序 + inflate(context, R.layout.note_item, this);//Inflate可用于将一个xml中定义的布局控件找出来,这里的xml是r。layout + //findViewById用于从contentView中查找指定ID的View,转换出来的形式根据需要而定; + mAlert = (ImageView) findViewById(R.id.iv_alert_icon); + mTitle = (TextView) findViewById(R.id.tv_title); + mTime = (TextView) findViewById(R.id.tv_time); + mCallName = (TextView) findViewById(R.id.tv_name); + mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); + } + ///根据data的属性对各个控件的属性的控制,主要是可见性Visibility,内容setText,格式setTextAppearance + public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { + if (choiceMode && data.getType() == Notes.TYPE_NOTE) { + mCheckBox.setVisibility(View.VISIBLE); ///设置可见行为可见 + mCheckBox.setChecked(checked); ///格子打钩 + } else { + mCheckBox.setVisibility(View.GONE); + } + + mItemData = data; + ///设置控件属性,一共三种情况,由data的id和父id是否与保存到文件夹的id一致来决定 + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mCallName.setVisibility(View.GONE); + mAlert.setVisibility(View.VISIBLE); + //设置该textview的style + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + //settext为设置内容 + mTitle.setText(context.getString(R.string.call_record_folder_name) + + context.getString(R.string.format_folder_files_count, data.getNotesCount())); + mAlert.setImageResource(R.drawable.call_record); + } else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { + mCallName.setVisibility(View.VISIBLE); + mCallName.setText(data.getCallName()); + mTitle.setTextAppearance(context,R.style.TextAppearanceSecondaryItem); + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + ///关于闹钟的设置 + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock);//图片来源的设置 + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } else { + mCallName.setVisibility(View.GONE); + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + ///设置title格式 + if (data.getType() == Notes.TYPE_FOLDER) { + mTitle.setText(data.getSnippet() + + context.getString(R.string.format_folder_files_count, + data.getNotesCount())); + mAlert.setVisibility(View.GONE); + } else { + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock);///设置图片来源 + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } + } + ///设置内容,获取相关时间,从data里编辑的日期中获取 + mTime. setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); + + setBackground(data); + } + //根据data的文件属性来设置背景 + private void setBackground(NoteItemData data) { + int id = data.getBgColorId(); + //,若是note型文件,则4种情况,对于4种不同情况的背景来源 + if (data.getType() == Notes.TYPE_NOTE) { + //单个数据并且只有一个子文件夹 + if (data.isSingle() || data.isOneFollowingFolder()) { + setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id)); + } else if (data.isLast()) {//是最后一个数据 + setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id)); + } else if (data.isFirst() || data.isMultiFollowingFolder()) {//是一个数据并有多个子文件夹 + setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id)); + } else { + setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id)); + } + } else { + //若不是note直接调用文件夹的背景来源 + setBackgroundResource(NoteItemBgResources.getFolderBgRes()); + } + } + public NoteItemData getItemData() { + return mItemData; + } +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java b/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java new file mode 100644 index 0000000..e4109c6 --- /dev/null +++ b/src/main/java/net/micode/notes/ui/NotesPreferenceActivity.java @@ -0,0 +1,492 @@ +package net.micode.notes.ui; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.ActionBar; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.remote.GTaskSyncService; + +/** + * @Package: net.micode.notes.ui + * @ClassName: NotesPreferenceActivity + * @Description: + * NotesPreferenceActivity,在小米便签中主要实现的是对背景颜色和字体大小的数据储存。 + * 继承了PreferenceActivity主要功能为对系统信息和配置进行自动保存的Activity + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:42 PM + * @Version: 1.0 + */ +public class NotesPreferenceActivity extends PreferenceActivity { + public static final String PREFERENCE_NAME = "notes_preferences";//优先名 + public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name";//同步账号 + public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time";//同步时间 + public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; + private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key";//同步密码 + private static final String AUTHORITIES_FILTER_KEY = "authorities"; + private PreferenceCategory mAccountCategory;//账户分组 + private GTaskReceiver mReceiver;//同步任务接收器 + private Account[] mOriAccounts;//账户 + private boolean mHasAddedAccount;//账户的hash标记 + + @Override + /** + * @method onCreate + * @description 创建一个activity,在函数里要完成所有的正常静态设置 + * @date: 12/23/2023 11:43 PM + * @author: YangYizhe + * @param [icicle] + * @return void + */ + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + /* using the app icon for navigation */ + getActionBar().setDisplayHomeAsUpEnabled(true);//给左上角图标的左边加上一个返回的图标 + addPreferencesFromResource(R.xml.preferences);//添加xml来源并显示 xml + mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY);//根据同步账户关键码来初始化分组 + mReceiver = new GTaskReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); + registerReceiver(mReceiver, filter);//初始化同步组件 + mOriAccounts = null; + View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null);//获取listvivew,ListView的作用:用于列出所有选择 + getListView().addHeaderView(header, null, true);//在listview组件上方添加其他组件 + } + + @Override + /** + * @method onResume + * @description activity交互功能的实现,用于接受用户的输入 + * @date: 12/23/2023 11:44 PM + * @author: YangYizhe + * @return void + */ + protected void onResume() { + super.onResume(); + + // need to set sync account automatically if user has added a new + // account + if (mHasAddedAccount) { + //若用户新加了账户则自动设置同步账户 + Account[] accounts = getGoogleAccounts();//获取google同步账户 + if (mOriAccounts != null && accounts.length > mOriAccounts.length) { + //若原账户不为空且当前账户有增加 + for (Account accountNew : accounts) { + boolean found = false; + for (Account accountOld : mOriAccounts) { + if (TextUtils.equals(accountOld.name, accountNew.name)) { + //更新账户 + found = true; + break; + } + } + if (!found) { + setSyncAccount(accountNew.name); + //若是没有找到旧的账户,那么同步账号中就只添加新账户 + break; + } + } + } + } + + refreshUI();//刷新标签界面 + } + + @Override + protected void onDestroy() { + if (mReceiver != null) { + unregisterReceiver(mReceiver);//注销接收器 + } + super.onDestroy();//执行父类的销毁动作 + } + + /** + * @method loadAccountPreference + * @description 重新设置账户信息 + * @date: 12/23/2023 11:45 PM + * @author: YangYizhe + * @param + * @return + */ + private void loadAccountPreference() { + mAccountCategory.removeAll();//销毁所有的分组 + Preference accountPref = new Preference(this);//建立首选项 + final String defaultAccount = getSyncAccountName(this); + accountPref.setTitle(getString(R.string.preferences_account_title)); + accountPref.setSummary(getString(R.string.preferences_account_summary));//设置首选项的大标题和小标题 + accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + //建立监听器 + if (!GTaskSyncService.isSyncing()) { + if (TextUtils.isEmpty(defaultAccount)) { + // the first time to set account + //若是第一次建立账户显示选择账户提示对话框 + showSelectAccountAlertDialog(); + } else { + // if the account has already been set, we need to promp + // user about the risk + //若是已经建立则显示修改对话框并进行修改操作 + showChangeAccountConfirmAlertDialog(); + } + } else { + //若在没有同步的情况下,则在toast中显示不能修改 + Toast.makeText(NotesPreferenceActivity.this, + R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT) + .show(); + } + return true; + } + }); + mAccountCategory.addPreference(accountPref);//根据新建首选项编辑新的账户分组 + } + /** + * @method loadSyncButton + * @description 设置按键的状态和最后同步的时间 + * @date: 12/23/2023 11:46 PM + * @author: YangYizhe + * @param + * @return + */ + private void loadSyncButton() { + Button syncButton = (Button) findViewById(R.id.preference_sync_button); + TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + //获取同步按钮控件和最终同步时间的的窗口 + // set button state + //设置按钮的状态 + if (GTaskSyncService.isSyncing()) { + //若是在同步状态下 + syncButton.setText(getString(R.string.preferences_button_sync_cancel)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.cancelSync(NotesPreferenceActivity.this); + } + });//设置按钮显示的文本为“取消同步”以及监听器 + } else { + syncButton.setText(getString(R.string.preferences_button_sync_immediately)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.startSync(NotesPreferenceActivity.this); + } + });//若是不同步则设置按钮显示的文本为“立即同步”以及对应监听器 + } + syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this)));//设置按键可用还是不可用 + // set last sync time + // 设置最终同步时间 + if (GTaskSyncService.isSyncing()) { + //若是在同步的情况下 + lastSyncTimeView.setText(GTaskSyncService.getProgressString()); + lastSyncTimeView.setVisibility(View.VISIBLE); + // 根据当前同步服务器设置时间显示框的文本以及可见性 + } else { + //若是非同步情况 + long lastSyncTime = getLastSyncTime(this); + if (lastSyncTime != 0) { + lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time, + DateFormat.format(getString(R.string.preferences_last_sync_time_format), + lastSyncTime))); + lastSyncTimeView.setVisibility(View.VISIBLE); + //则根据最后同步时间的信息来编辑时间显示框的文本内容和可见性 + } else { + //若时间为空直接设置为不可见状态 + lastSyncTimeView.setVisibility(View.GONE); + } + } + } + /** + * @method refreshUI + * @description + * 刷新标签界面 + * 调用上文设置账号和设置按键两个函数来实现 + * @date: 12/23/2023 11:46 PM + * @author: YangYizhe + */ + private void refreshUI() { + loadAccountPreference(); + loadSyncButton(); + } + /** + * @method showSelectAccountAlertDialog + * @description 显示账户选择的对话框并进行账户的设置 + * @date: 12/23/2023 11:47 PM + * @author: YangYizhe + * @param + * @return + */ + private void showSelectAccountAlertDialog() { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框 + + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); + TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); + titleTextView.setText(getString(R.string.preferences_dialog_select_account_title)); + TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); + subtitleTextView.setText(getString(R.string.preferences_dialog_select_account_tips));//设置标题以及子标题的内容 + dialogBuilder.setCustomTitle(titleView); + dialogBuilder.setPositiveButton(null, null);//设置对话框的自定义标题,建立一个YES的按钮 + Account[] accounts = getGoogleAccounts(); + String defAccount = getSyncAccountName(this);//获取同步账户信息 + mOriAccounts = accounts; + mHasAddedAccount = false; + + if (accounts.length > 0) { + //若账户不为空 + CharSequence[] items = new CharSequence[accounts.length]; + final CharSequence[] itemMapping = items; + int checkedItem = -1; + int index = 0; + for (Account account : accounts) { + if (TextUtils.equals(account.name, defAccount)) { + checkedItem = index;//在账户列表中查询到所需账户 + } + items[index++] = account.name; + } + dialogBuilder.setSingleChoiceItems(items, checkedItem, + //在对话框建立一个单选的复选框 + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + setSyncAccount(itemMapping[which].toString()); + dialog.dismiss();//取消对话框 + refreshUI(); + } + });//建立对话框网络版的监听器 + } + + View addAccountView = LayoutInflater.from(this).inflate(R.layout.add_account_text, null); + dialogBuilder.setView(addAccountView);//给新加账户对话框设置自定义样式 + + final AlertDialog dialog = dialogBuilder.show();//显示对话框 + addAccountView.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mHasAddedAccount = true; + //将新加账户的hash置true + Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); + //建立网络建立组件 + intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] { + "gmail-ls" + }); + startActivityForResult(intent, -1); + //跳回上一个选项 + dialog.dismiss(); + } + });//建立新加账户对话框的监听器 + } + /** + * @method showChangeAccountConfirmAlertDialog + * @description 显示账户选择对话框和相关账户操作 + * @date: 12/23/2023 11:48 PM + * @author: YangYizhe + */ + private void showChangeAccountConfirmAlertDialog() { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);//创建一个新的对话框 + View titleView = LayoutInflater.from(this).inflate(R.layout.account_dialog_title, null); + TextView titleTextView = (TextView) titleView.findViewById(R.id.account_dialog_title); + titleTextView.setText(getString(R.string.preferences_dialog_change_account_title, + getSyncAccountName(this))); + TextView subtitleTextView = (TextView) titleView.findViewById(R.id.account_dialog_subtitle); + subtitleTextView.setText(getString(R.string.preferences_dialog_change_account_warn_msg));//根据同步修改的账户信息设置标题以及子标题的内容 + dialogBuilder.setCustomTitle(titleView);//设置对话框的自定义标题 + CharSequence[] menuItemArray = new CharSequence[] { + getString(R.string.preferences_menu_change_account), + getString(R.string.preferences_menu_remove_account), + getString(R.string.preferences_menu_cancel) + }; + dialogBuilder.setItems(menuItemArray, new DialogInterface.OnClickListener() { + //设置对话框要显示的一个list,用于显示几个命令时,即change,remove,cancel + public void onClick(DialogInterface dialog, int which) { + //按键功能,由which来决定 + if (which == 0) { + //进入账户选择对话框 + showSelectAccountAlertDialog(); + } else if (which == 1) { + //删除账户并且跟新便签界面 + removeSyncAccount(); + refreshUI(); + } + } + }); + dialogBuilder.show();//显示对话框 + } + + /** + * @method getGoogleAccounts + * @description + * 获取谷歌账户 + * 通过账户管理器直接获取 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + */ + private Account[] getGoogleAccounts() { + AccountManager accountManager = AccountManager.get(this); + return accountManager.getAccountsByType("com.google"); + } + + /** + * @method setSyncAccount + * @description 设置同步账户 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + * @param account + */ + private void setSyncAccount(String account) { + if (!getSyncAccountName(this).equals(account)) { + //假如该账号不在同步账号列表中 + SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();//编辑共享的首选项 + if (account != null) { + editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, account); + } else { + editor.putString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); + }//将该账号加入到首选项中 + + editor.commit();//提交修改的数据 + setLastSyncTime(this, 0);//将最后同步时间清零 + + // clean up local gtask related info + new Thread(new Runnable() { + public void run() { + ContentValues values = new ContentValues(); + values.put(NoteColumns.GTASK_ID, ""); + values.put(NoteColumns.SYNC_ID, 0); + getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); + } + }).start(); + //重置当地同步任务的信息 + + Toast.makeText(NotesPreferenceActivity.this, + getString(R.string.preferences_toast_success_set_accout, account), + Toast.LENGTH_SHORT).show(); + //将toast的文本信息置为“设置账户成功”并显示出来 + } + } + /** + * @method removeSyncAccount + * @description 删除同步账户 + * @date: 12/23/2023 11:49 PM + * @author: YangYizhe + */ + private void removeSyncAccount() { + SharedPreferences settings = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();//设置共享首选项 + + if (settings.contains(PREFERENCE_SYNC_ACCOUNT_NAME)) { + editor.remove(PREFERENCE_SYNC_ACCOUNT_NAME);//假如当前首选项中有账户就删除 + } + if (settings.contains(PREFERENCE_LAST_SYNC_TIME)) { + editor.remove(PREFERENCE_LAST_SYNC_TIME);//删除当前首选项中有账户时间 + } + editor.commit();//提交更新后的数据 + + // clean up local gtask related info + new Thread(new Runnable() { + public void run() { + ContentValues values = new ContentValues(); + values.put(NoteColumns.GTASK_ID, ""); + values.put(NoteColumns.SYNC_ID, 0); + getContentResolver().update(Notes.CONTENT_NOTE_URI, values, null, null); + } + }).start(); + //重置当地同步任务的信息 + } + /** + * @method getSyncAccountName + * @description + * 获取同步账户名称 + * 通过共享的首选项里的信息直接获取 + * @date: 12/23/2023 11:50 PM + * @author: YangYizhe + * @param context + */ + public static String getSyncAccountName(Context context) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + return settings.getString(PREFERENCE_SYNC_ACCOUNT_NAME, ""); + } + /** + * @method setLastSyncTime + * @description 设置最终同步的时间 + * @date: 12/23/2023 11:50 PM + * @author: YangYizhe + * @param + * @return + */ + public static void setLastSyncTime(Context context, long time) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit();// 从共享首选项中找到相关账户并获取其编辑器 + editor.putLong(PREFERENCE_LAST_SYNC_TIME, time); + editor.commit();//编辑最终同步时间并提交更新 + } + /** + * @method getLastSyncTime + * @description + * 获取最终同步时间 + * 通过共享的首选项里的信息直接获取 + * @date: 12/23/2023 11:51 PM + * @author: YangYizhe + * @param context + */ + public static long getLastSyncTime(Context context) { + SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, + Context.MODE_PRIVATE); + return settings.getLong(PREFERENCE_LAST_SYNC_TIME, 0); + } + + private class GTaskReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + refreshUI(); + if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) { + //获取随广播而来的Intent中的同步服务的数据 + TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + syncStatus.setText(intent + .getStringExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_PROGRESS_MSG));//通过获取的数据在设置系统的状态 + } + + } + } + /** + * @method onOptionsItemSelected + * @description 处理菜单的选项 + * @date: 12/23/2023 11:52 PM + * @author: YangYizhe + * @param item + */ + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + //根据选项的id选择,这里只有一个主页 + case android.R.id.home: + Intent intent = new Intent(this, NotesListActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + //在主页情况下在创建连接组件intent,发出清空的信号并开始一个相应的activity + default: + return false; + } + } +} + \ No newline at end of file diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java new file mode 100644 index 0000000..d8eb50b --- /dev/null +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.util.Log; +import android.widget.RemoteViews; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NoteEditActivity; +import net.micode.notes.ui.NotesListActivity; +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider + * @Description: 这个抽象类用作MiNote应用程序中笔记小部件的基础。它提供了在主屏幕上更新和管理笔记小部件的功能。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:53 PM + * @Version: 1.0 + */ +public abstract class NoteWidgetProvider extends AppWidgetProvider { + public static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.BG_COLOR_ID, + NoteColumns.SNIPPET + }; + + public static final int COLUMN_ID = 0; + public static final int COLUMN_BG_COLOR_ID = 1; + public static final int COLUMN_SNIPPET = 2; + + private static final String TAG = "NoteWidgetProvider"; + + @Override + public void onDeleted(Context context, int[] appWidgetIds) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + for (int i = 0; i < appWidgetIds.length; i++) { + context.getContentResolver().update(Notes.CONTENT_NOTE_URI, + values, + NoteColumns.WIDGET_ID + "=?", + new String[] { String.valueOf(appWidgetIds[i])}); + } + } + + private Cursor getNoteWidgetInfo(Context context, int widgetId) { + return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, + null); + } + + protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + update(context, appWidgetManager, appWidgetIds, false); + } + + private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, + boolean privacyMode) { + for (int i = 0; i < appWidgetIds.length; i++) { + if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + int bgId = ResourceParser.getDefaultBgId(context); + String snippet = ""; + Intent intent = new Intent(context, NoteEditActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); + + Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); + if (c != null && c.moveToFirst()) { + if (c.getCount() > 1) { + Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); + c.close(); + return; + } + snippet = c.getString(COLUMN_SNIPPET); + bgId = c.getInt(COLUMN_BG_COLOR_ID); + intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); + intent.setAction(Intent.ACTION_VIEW); + } else { + snippet = context.getResources().getString(R.string.widget_havenot_content); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + } + + if (c != null) { + c.close(); + } + + RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); + rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); + intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); + /** + * Generate the pending intent to start host for the widget + */ + PendingIntent pendingIntent = null; + if (privacyMode) { + rv.setTextViewText(R.id.widget_text, + context.getString(R.string.widget_under_visit_mode)); + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( + context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + } else { + rv.setTextViewText(R.id.widget_text, snippet); + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, + PendingIntent.FLAG_UPDATE_CURRENT); + } + + rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); + appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + } + } + } + + protected abstract int getBgResourceId(int bgId); + + protected abstract int getLayoutId(); + + protected abstract int getWidgetType(); +} diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java new file mode 100644 index 0000000..f3d5f1e --- /dev/null +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Context; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.ResourceParser; + +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider_2x + * @Description: + * 这个类是NoteWidgetProvider的一个具体实现,用于实现2x大小的笔记小部件。 + * 它继承自NoteWidgetProvider,并提供特定于2x小部件的布局ID、背景资源和小部件类型。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:55 PM + * @Version: 1.0 + */ +public class NoteWidgetProvider_2x extends NoteWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + super.update(context, appWidgetManager, appWidgetIds); + } + + @Override + protected int getLayoutId() { + return R.layout.widget_2x; + } + + @Override + protected int getBgResourceId(int bgId) { + return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); + } + + @Override + protected int getWidgetType() { + return Notes.TYPE_WIDGET_2X; + } +} diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java new file mode 100644 index 0000000..0c3ae50 --- /dev/null +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Context; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.ResourceParser; + +/** + * @Package: net.micode.notes.widget + * @ClassName: NoteWidgetProvider_4x + * @Description: + * 这个类是NoteWidgetProvider的一个具体实现,用于实现4x大小的笔记小部件。 + * 它继承自NoteWidgetProvider,并提供特定于4x小部件的布局ID、背景资源和小部件类型。 + * @Author: YangYizhe + * @CreateDate: 12/23/2023 11:56 PM + * @Version: 1.0 + */ +public class NoteWidgetProvider_4x extends NoteWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + super.update(context, appWidgetManager, appWidgetIds); + } + + protected int getLayoutId() { + return R.layout.widget_4x; + } + + @Override + protected int getBgResourceId(int bgId) { + return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); + } + + @Override + protected int getWidgetType() { + return Notes.TYPE_WIDGET_4X; + } +} diff --git a/src/main/res/layout/note_edit.xml b/src/main/res/layout/note_edit.xml index 9aa4ad9..4f0126b 100644 --- a/src/main/res/layout/note_edit.xml +++ b/src/main/res/layout/note_edit.xml @@ -99,13 +99,13 @@ android:id="@+id/note_edit_view" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:autoLink="all" - android:background="@null" android:gravity="left|top" - android:lineSpacingMultiplier="1.2" + android:background="@null" + android:autoLink="all" android:linksClickable="false" android:minLines="12" - android:textAppearance="@style/TextAppearancePrimaryItem" /> + android:textAppearance="@style/TextAppearancePrimaryItem" + android:lineSpacingMultiplier="1.2" /> + android:background="@drawable/list_background"> - - - - - - - - - - diff --git a/src/main/res/menu/sub_folder.xml b/src/main/res/menu/sub_folder.xml index d81e568..b00de26 100644 --- a/src/main/res/menu/sub_folder.xml +++ b/src/main/res/menu/sub_folder.xml @@ -21,20 +21,4 @@ - - - - - - - - \ No newline at end of file diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index dacfe89..09f75ed 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -119,14 +119,6 @@ 便签 设置 取消 - 亮背景 - 暗背景 - 私密模式 - 退出私密模式 - 字符数 - 恢复 - 欢迎页面 - EAZZY\nNOTE %1$s 条符合“%2$s”的搜索结果 diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index 1bfa120..e29b79b 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -120,14 +120,6 @@ 便籤 設置 取消 - 亮背景 - 暗背景 - 私密模式 - 退出私密模式 - 字符数 - 恢复 - 欢迎页面 - EAZZY\nNOTE %1$s 條符合”%2$s“的搜尋結果 diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml index 2496c0c..123ffbf 100644 --- a/src/main/res/values/colors.xml +++ b/src/main/res/values/colors.xml @@ -17,9 +17,4 @@ #335b5b5b - #FF039BE5 - #FF01579B - #FF40C4FF - #FF00B0FF - #66000000 diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 469b04c..55df868 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -15,7 +15,8 @@ limitations under the License. --> - + Notes Notes 2x2 Notes 4x4 @@ -125,24 +126,10 @@ Notes set cancel - - light mode - dark mode - - secret mode - quit secret mode - - length - restore - - SplashActivity - EAZZY\nNOTE - - %1$s result for \"%2$s\" + %1$s result for \"%2$s\" - %1$s results for \"%2$s\" + %1$s results for \"%2$s\" - diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml index db56d26..ad0d90d 100644 --- a/src/main/res/values/styles.xml +++ b/src/main/res/values/styles.xml @@ -16,22 +16,18 @@ --> - - - - @@ -70,13 +66,4 @@ visible - - - - \ No newline at end of file