diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d113d3511..000000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "extern/Support"] - path = extern/Support - url = https://android.googlesource.com/platform/frameworks/support - ignore = dirty diff --git a/CHANGELOG.md b/CHANGELOG.md index a71f271dd..458388b1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ -### Upcoming release +### 0.95 (2015-08-04) -* Adapt UI to use Material Design +* Start porting UI to Material Design, including a new launcher icon + +* Add support for app changelog links, which will appear for apps that have + them once the repositories have been updated again * Redesign the App Details view with larger icons, expandable description and links with icons @@ -11,11 +14,16 @@ * Remove the root installer, since the system installer is safer, more stable and now easy to set up with root privileges +* Speed up and simplify repo update process by streaming the data out of the + jar file directly + * Can now manually add swap repo via "Repositories" screen * Using NFC during swap now initiates a proper swap, rather than redirecting to the "Repositories" screen +* Drop ant support to greatly simplify the build process and its maintenance + ### 0.92 (2015-06-08) * Make swap only in portrait mode to prevent crashes and issues where UI elements are obscured diff --git a/F-Droid/AndroidManifest.xml b/F-Droid/AndroidManifest.xml index b75b27df5..9344576ad 100644 --- a/F-Droid/AndroidManifest.xml +++ b/F-Droid/AndroidManifest.xml @@ -3,8 +3,8 @@ xmlns:tools="http://schemas.android.com/tools" package="org.fdroid.fdroid" android:installLocation="auto" - android:versionCode="940" - android:versionName="0.94-test" + android:versionCode="95050" + android:versionName="0.95" > <uses-sdk @@ -62,7 +62,7 @@ android:label="@string/app_name" android:description="@string/app_description" android:allowBackup="true" - android:theme="@style/AppThemeDark" + android:theme="@style/AppThemeLight" android:supportsRtl="true" > diff --git a/F-Droid/build.gradle b/F-Droid/build.gradle index 1d994dc85..5f6240f5a 100644 --- a/F-Droid/build.gradle +++ b/F-Droid/build.gradle @@ -109,8 +109,7 @@ task binaryDeps(type: Copy, dependsOn: ':F-Droid:prepareReleaseDependencies') { include 'support-v4-preferencefragment/build/outputs/aar/support-v4-preferencefragment-release.aar', 'nanohttpd/core/build/libs/nanohttpd-2.1.0.jar', 'zipsigner/build/libs/zipsigner.jar', - 'jmdns/build/libs/jmdns.jar', - 'Support/v4/build/libs/support-v4.jar' + 'jmdns/build/libs/jmdns.jar' } into 'libs/binaryDeps' @@ -174,6 +173,9 @@ android { lintOptions { checkReleaseBuilds false abortOnError false + + // Our translations are crowd-sourced + disable 'MissingTranslation' } // Enable all Android lint warnings diff --git a/F-Droid/libs/README.md b/F-Droid/libs/README.md index a338d672c..430057598 100644 --- a/F-Droid/libs/README.md +++ b/F-Droid/libs/README.md @@ -1,8 +1,10 @@ # Licenses -To see which license any one of these libraries is under, consult the extern/ directory. -If you have checked out the source for all dependencies (`git submodule update --init` from the root directory), -then you should be able to find the relevant LICENSE file for each, or else you can consult upstream. +To see which license any one of these libraries is under, consult the extern/ +directory. If you have checked out the source for all dependencies (`git +submodule update --init` from the root directory if there are any submodules), +then you should be able to find the relevant LICENSE file for each, or else +you can consult upstream. # Building libraries from source diff --git a/F-Droid/libs/android-support-v4.jar b/F-Droid/libs/android-support-v4.jar deleted file mode 100644 index 4ebdaa9ed..000000000 Binary files a/F-Droid/libs/android-support-v4.jar and /dev/null differ diff --git a/F-Droid/lint.xml b/F-Droid/lint.xml deleted file mode 100644 index 348e7f6ce..000000000 --- a/F-Droid/lint.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<lint> - <!-- Remove severity="ignore" to see the missing translations --> - <issue id="MissingTranslation" severity="ignore" /> - <issue id="TrulyRandom" severity="ignore" /> - <issue id="UnusedResources" severity="ignore"> - <ignore path="res/values/default_repo.xml" /> - </issue> -</lint> \ No newline at end of file diff --git a/F-Droid/res/drawable-hdpi/ic_add_white.png b/F-Droid/res/drawable-hdpi/ic_add_white.png index 72cedcad4..694179bd4 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_add_white.png and b/F-Droid/res/drawable-hdpi/ic_add_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_bluetooth_white.png b/F-Droid/res/drawable-hdpi/ic_bluetooth_white.png index bf5912471..fce188400 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_bluetooth_white.png and b/F-Droid/res/drawable-hdpi/ic_bluetooth_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_bullet_key_permission.png b/F-Droid/res/drawable-hdpi/ic_bullet_key_permission.png deleted file mode 100644 index 4cf50ade1..000000000 Binary files a/F-Droid/res/drawable-hdpi/ic_bullet_key_permission.png and /dev/null differ diff --git a/F-Droid/res/drawable-hdpi/ic_clear.png b/F-Droid/res/drawable-hdpi/ic_clear.png new file mode 100644 index 000000000..1a9cd75a0 Binary files /dev/null and b/F-Droid/res/drawable-hdpi/ic_clear.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_delete_white.png b/F-Droid/res/drawable-hdpi/ic_delete_white.png index 0e95e9b1d..4a9f76947 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_delete_white.png and b/F-Droid/res/drawable-hdpi/ic_delete_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_do_not_disturb_white.png b/F-Droid/res/drawable-hdpi/ic_do_not_disturb_white.png index bb07825f1..34ccc229d 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_do_not_disturb_white.png and b/F-Droid/res/drawable-hdpi/ic_do_not_disturb_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_edit_white.png b/F-Droid/res/drawable-hdpi/ic_edit_white.png deleted file mode 100644 index 34ec7092f..000000000 Binary files a/F-Droid/res/drawable-hdpi/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-hdpi/ic_help_white.png b/F-Droid/res/drawable-hdpi/ic_help_white.png index 1173aed08..5664f9532 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_help_white.png and b/F-Droid/res/drawable-hdpi/ic_help_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_menu_refresh.png b/F-Droid/res/drawable-hdpi/ic_menu_refresh.png deleted file mode 100644 index 40ab9862b..000000000 Binary files a/F-Droid/res/drawable-hdpi/ic_menu_refresh.png and /dev/null differ diff --git a/F-Droid/res/drawable-hdpi/ic_nfc_white.png b/F-Droid/res/drawable-hdpi/ic_nfc_white.png index 78db0e17e..8aea57d31 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_nfc_white.png and b/F-Droid/res/drawable-hdpi/ic_nfc_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_play_arrow_white.png b/F-Droid/res/drawable-hdpi/ic_play_arrow_white.png index 043acd808..57c9fa546 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_play_arrow_white.png and b/F-Droid/res/drawable-hdpi/ic_play_arrow_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_refresh_white.png b/F-Droid/res/drawable-hdpi/ic_refresh_white.png index 72128fe69..ffa7be933 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_refresh_white.png and b/F-Droid/res/drawable-hdpi/ic_refresh_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_search_white.png b/F-Droid/res/drawable-hdpi/ic_search_white.png index 0bbeab150..bbfbc96cb 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_search_white.png and b/F-Droid/res/drawable-hdpi/ic_search_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_settings_white.png b/F-Droid/res/drawable-hdpi/ic_settings_white.png index 6bb8f6e08..97ded33b5 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_settings_white.png and b/F-Droid/res/drawable-hdpi/ic_settings_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_share_white.png b/F-Droid/res/drawable-hdpi/ic_share_white.png index 9963c6a05..b09a6926d 100644 Binary files a/F-Droid/res/drawable-hdpi/ic_share_white.png and b/F-Droid/res/drawable-hdpi/ic_share_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_toc_white.png b/F-Droid/res/drawable-hdpi/ic_toc_white.png new file mode 100644 index 000000000..bb3adfa89 Binary files /dev/null and b/F-Droid/res/drawable-hdpi/ic_toc_white.png differ diff --git a/F-Droid/res/drawable-hdpi/ic_view_headline_white.png b/F-Droid/res/drawable-hdpi/ic_view_headline_white.png deleted file mode 100644 index 4f9458b1a..000000000 Binary files a/F-Droid/res/drawable-hdpi/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-ldpi/ic_bullet_key_permission.png b/F-Droid/res/drawable-ldpi/ic_bullet_key_permission.png deleted file mode 100644 index 4aff20ce9..000000000 Binary files a/F-Droid/res/drawable-ldpi/ic_bullet_key_permission.png and /dev/null differ diff --git a/F-Droid/res/drawable-ldpi/ic_menu_refresh.png b/F-Droid/res/drawable-ldpi/ic_menu_refresh.png deleted file mode 100644 index 8e3ff8927..000000000 Binary files a/F-Droid/res/drawable-ldpi/ic_menu_refresh.png and /dev/null differ diff --git a/F-Droid/res/drawable-mdpi/ic_add_white.png b/F-Droid/res/drawable-mdpi/ic_add_white.png index 67042105d..3856041d7 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_add_white.png and b/F-Droid/res/drawable-mdpi/ic_add_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_bluetooth_white.png b/F-Droid/res/drawable-mdpi/ic_bluetooth_white.png index 678678da4..27a8a719f 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_bluetooth_white.png and b/F-Droid/res/drawable-mdpi/ic_bluetooth_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_bullet_key_permission.png b/F-Droid/res/drawable-mdpi/ic_bullet_key_permission.png deleted file mode 100644 index 7fee56024..000000000 Binary files a/F-Droid/res/drawable-mdpi/ic_bullet_key_permission.png and /dev/null differ diff --git a/F-Droid/res/drawable-mdpi/ic_clear.png b/F-Droid/res/drawable-mdpi/ic_clear.png new file mode 100644 index 000000000..40a1a84e3 Binary files /dev/null and b/F-Droid/res/drawable-mdpi/ic_clear.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_delete_white.png b/F-Droid/res/drawable-mdpi/ic_delete_white.png index cdb230c2f..e2f5f3555 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_delete_white.png and b/F-Droid/res/drawable-mdpi/ic_delete_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_do_not_disturb_white.png b/F-Droid/res/drawable-mdpi/ic_do_not_disturb_white.png index 4e4fa1e59..3e87dde72 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_do_not_disturb_white.png and b/F-Droid/res/drawable-mdpi/ic_do_not_disturb_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_edit_white.png b/F-Droid/res/drawable-mdpi/ic_edit_white.png deleted file mode 100644 index 7f0ea51bf..000000000 Binary files a/F-Droid/res/drawable-mdpi/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-mdpi/ic_help_white.png b/F-Droid/res/drawable-mdpi/ic_help_white.png index 9f8051b44..db699622b 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_help_white.png and b/F-Droid/res/drawable-mdpi/ic_help_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_menu_refresh.png b/F-Droid/res/drawable-mdpi/ic_menu_refresh.png deleted file mode 100644 index ceb6842af..000000000 Binary files a/F-Droid/res/drawable-mdpi/ic_menu_refresh.png and /dev/null differ diff --git a/F-Droid/res/drawable-mdpi/ic_nfc_white.png b/F-Droid/res/drawable-mdpi/ic_nfc_white.png index 428351e8e..cdadd9eef 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_nfc_white.png and b/F-Droid/res/drawable-mdpi/ic_nfc_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_play_arrow_white.png b/F-Droid/res/drawable-mdpi/ic_play_arrow_white.png index a55d19922..c61e948bb 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_play_arrow_white.png and b/F-Droid/res/drawable-mdpi/ic_play_arrow_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_refresh_white.png b/F-Droid/res/drawable-mdpi/ic_refresh_white.png index 5f89fc257..97e42b525 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_refresh_white.png and b/F-Droid/res/drawable-mdpi/ic_refresh_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_search_white.png b/F-Droid/res/drawable-mdpi/ic_search_white.png index 043759acd..faefc59c8 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_search_white.png and b/F-Droid/res/drawable-mdpi/ic_search_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_settings_white.png b/F-Droid/res/drawable-mdpi/ic_settings_white.png index 12e5d100d..8909c3553 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_settings_white.png and b/F-Droid/res/drawable-mdpi/ic_settings_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_share_white.png b/F-Droid/res/drawable-mdpi/ic_share_white.png index dd536bca2..e944fd70c 100644 Binary files a/F-Droid/res/drawable-mdpi/ic_share_white.png and b/F-Droid/res/drawable-mdpi/ic_share_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_toc_white.png b/F-Droid/res/drawable-mdpi/ic_toc_white.png new file mode 100644 index 000000000..2a386add0 Binary files /dev/null and b/F-Droid/res/drawable-mdpi/ic_toc_white.png differ diff --git a/F-Droid/res/drawable-mdpi/ic_view_headline_white.png b/F-Droid/res/drawable-mdpi/ic_view_headline_white.png deleted file mode 100644 index e6ecf5a1d..000000000 Binary files a/F-Droid/res/drawable-mdpi/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xhdpi/ic_add_white.png b/F-Droid/res/drawable-xhdpi/ic_add_white.png index 2bef05958..67bb598e5 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_add_white.png and b/F-Droid/res/drawable-xhdpi/ic_add_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_bluetooth_white.png b/F-Droid/res/drawable-xhdpi/ic_bluetooth_white.png index e3fe3cfbb..920f5cae7 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_bluetooth_white.png and b/F-Droid/res/drawable-xhdpi/ic_bluetooth_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_bullet_key_permission.png b/F-Droid/res/drawable-xhdpi/ic_bullet_key_permission.png deleted file mode 100644 index 6a0bdfcb1..000000000 Binary files a/F-Droid/res/drawable-xhdpi/ic_bullet_key_permission.png and /dev/null differ diff --git a/F-Droid/res/drawable-xhdpi/ic_clear.png b/F-Droid/res/drawable-xhdpi/ic_clear.png new file mode 100644 index 000000000..6bc437298 Binary files /dev/null and b/F-Droid/res/drawable-xhdpi/ic_clear.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_delete_white.png b/F-Droid/res/drawable-xhdpi/ic_delete_white.png index e69de29bb..388b5b060 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_delete_white.png and b/F-Droid/res/drawable-xhdpi/ic_delete_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_do_not_disturb_white.png b/F-Droid/res/drawable-xhdpi/ic_do_not_disturb_white.png index 38f12a7b5..dc5e1ac59 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_do_not_disturb_white.png and b/F-Droid/res/drawable-xhdpi/ic_do_not_disturb_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_edit_white.png b/F-Droid/res/drawable-xhdpi/ic_edit_white.png deleted file mode 100644 index 9380370f4..000000000 Binary files a/F-Droid/res/drawable-xhdpi/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xhdpi/ic_help_white.png b/F-Droid/res/drawable-xhdpi/ic_help_white.png index 9b27847bb..2d11cf47a 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_help_white.png and b/F-Droid/res/drawable-xhdpi/ic_help_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_menu_refresh.png b/F-Droid/res/drawable-xhdpi/ic_menu_refresh.png deleted file mode 100644 index b94ecf9b6..000000000 Binary files a/F-Droid/res/drawable-xhdpi/ic_menu_refresh.png and /dev/null differ diff --git a/F-Droid/res/drawable-xhdpi/ic_nfc_white.png b/F-Droid/res/drawable-xhdpi/ic_nfc_white.png index 821029ce4..454a95024 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_nfc_white.png and b/F-Droid/res/drawable-xhdpi/ic_nfc_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_play_arrow_white.png b/F-Droid/res/drawable-xhdpi/ic_play_arrow_white.png index 7cc008475..a3c80e73d 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_play_arrow_white.png and b/F-Droid/res/drawable-xhdpi/ic_play_arrow_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_refresh_white.png b/F-Droid/res/drawable-xhdpi/ic_refresh_white.png index d271d8e03..1989184b1 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_refresh_white.png and b/F-Droid/res/drawable-xhdpi/ic_refresh_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_search_white.png b/F-Droid/res/drawable-xhdpi/ic_search_white.png index 70c21baf7..bfc3e3939 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_search_white.png and b/F-Droid/res/drawable-xhdpi/ic_search_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_settings_white.png b/F-Droid/res/drawable-xhdpi/ic_settings_white.png index 97e9ca945..5caedc8e5 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_settings_white.png and b/F-Droid/res/drawable-xhdpi/ic_settings_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_share_white.png b/F-Droid/res/drawable-xhdpi/ic_share_white.png index bb521c141..22a8783e7 100644 Binary files a/F-Droid/res/drawable-xhdpi/ic_share_white.png and b/F-Droid/res/drawable-xhdpi/ic_share_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_toc_white.png b/F-Droid/res/drawable-xhdpi/ic_toc_white.png new file mode 100644 index 000000000..7563e739c Binary files /dev/null and b/F-Droid/res/drawable-xhdpi/ic_toc_white.png differ diff --git a/F-Droid/res/drawable-xhdpi/ic_view_headline_white.png b/F-Droid/res/drawable-xhdpi/ic_view_headline_white.png deleted file mode 100644 index c66e9d234..000000000 Binary files a/F-Droid/res/drawable-xhdpi/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_add_white.png b/F-Droid/res/drawable-xxhdpi/ic_add_white.png index b12e040e0..0fdced8fc 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_add_white.png and b/F-Droid/res/drawable-xxhdpi/ic_add_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_bluetooth_white.png b/F-Droid/res/drawable-xxhdpi/ic_bluetooth_white.png index 6c8cb16af..860c75864 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_bluetooth_white.png and b/F-Droid/res/drawable-xxhdpi/ic_bluetooth_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_bullet_key_permission.png b/F-Droid/res/drawable-xxhdpi/ic_bullet_key_permission.png deleted file mode 100644 index a74c2862b..000000000 Binary files a/F-Droid/res/drawable-xxhdpi/ic_bullet_key_permission.png and /dev/null differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_clear.png b/F-Droid/res/drawable-xxhdpi/ic_clear.png new file mode 100644 index 000000000..51b4401ca Binary files /dev/null and b/F-Droid/res/drawable-xxhdpi/ic_clear.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_delete_white.png b/F-Droid/res/drawable-xxhdpi/ic_delete_white.png index a8d8ca84d..3fcdfdb55 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_delete_white.png and b/F-Droid/res/drawable-xxhdpi/ic_delete_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_do_not_disturb_white.png b/F-Droid/res/drawable-xxhdpi/ic_do_not_disturb_white.png index 9ac3d7a02..349b03f6c 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_do_not_disturb_white.png and b/F-Droid/res/drawable-xxhdpi/ic_do_not_disturb_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_edit_white.png b/F-Droid/res/drawable-xxhdpi/ic_edit_white.png deleted file mode 100644 index fe5bd13fb..000000000 Binary files a/F-Droid/res/drawable-xxhdpi/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_help_white.png b/F-Droid/res/drawable-xxhdpi/ic_help_white.png index f34516ecc..d49181785 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_help_white.png and b/F-Droid/res/drawable-xxhdpi/ic_help_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_nfc_white.png b/F-Droid/res/drawable-xxhdpi/ic_nfc_white.png index 81b19ef04..48d8e11f6 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_nfc_white.png and b/F-Droid/res/drawable-xxhdpi/ic_nfc_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_play_arrow_white.png b/F-Droid/res/drawable-xxhdpi/ic_play_arrow_white.png index de7f9bdb5..547ef30aa 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_play_arrow_white.png and b/F-Droid/res/drawable-xxhdpi/ic_play_arrow_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_refresh_white.png b/F-Droid/res/drawable-xxhdpi/ic_refresh_white.png index 87ab2d640..1692d8a24 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_refresh_white.png and b/F-Droid/res/drawable-xxhdpi/ic_refresh_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_search_white.png b/F-Droid/res/drawable-xxhdpi/ic_search_white.png index 75d9aa69f..abbb98951 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_search_white.png and b/F-Droid/res/drawable-xxhdpi/ic_search_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_settings_white.png b/F-Droid/res/drawable-xxhdpi/ic_settings_white.png index 5940812da..eabb0a2ba 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_settings_white.png and b/F-Droid/res/drawable-xxhdpi/ic_settings_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_share_white.png b/F-Droid/res/drawable-xxhdpi/ic_share_white.png index cf3072ecf..a35b3cd14 100644 Binary files a/F-Droid/res/drawable-xxhdpi/ic_share_white.png and b/F-Droid/res/drawable-xxhdpi/ic_share_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_toc_white.png b/F-Droid/res/drawable-xxhdpi/ic_toc_white.png new file mode 100644 index 000000000..108a026a9 Binary files /dev/null and b/F-Droid/res/drawable-xxhdpi/ic_toc_white.png differ diff --git a/F-Droid/res/drawable-xxhdpi/ic_view_headline_white.png b/F-Droid/res/drawable-xxhdpi/ic_view_headline_white.png deleted file mode 100644 index faccf3d23..000000000 Binary files a/F-Droid/res/drawable-xxhdpi/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_add_white.png b/F-Droid/res/drawable-xxxhdpi/ic_add_white.png index cd32f0a82..d64c22e9e 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_add_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_add_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_bluetooth_white.png b/F-Droid/res/drawable-xxxhdpi/ic_bluetooth_white.png index c0181e016..90d8a3413 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_bluetooth_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_bluetooth_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_clear.png b/F-Droid/res/drawable-xxxhdpi/ic_clear.png new file mode 100644 index 000000000..df42feecb Binary files /dev/null and b/F-Droid/res/drawable-xxxhdpi/ic_clear.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_delete_white.png b/F-Droid/res/drawable-xxxhdpi/ic_delete_white.png index 47fef5aab..8d322aa9b 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_delete_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_delete_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_do_not_disturb_white.png b/F-Droid/res/drawable-xxxhdpi/ic_do_not_disturb_white.png index 446abf648..144695ec0 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_do_not_disturb_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_do_not_disturb_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_edit_white.png b/F-Droid/res/drawable-xxxhdpi/ic_edit_white.png deleted file mode 100644 index 736806495..000000000 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_help_white.png b/F-Droid/res/drawable-xxxhdpi/ic_help_white.png index c99653261..8eb7241da 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_help_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_help_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_nfc_white.png b/F-Droid/res/drawable-xxxhdpi/ic_nfc_white.png index 12cd90eae..7051d7bd6 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_nfc_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_nfc_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_play_arrow_white.png b/F-Droid/res/drawable-xxxhdpi/ic_play_arrow_white.png index f4f713e83..be5c062b5 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_play_arrow_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_play_arrow_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_refresh_white.png b/F-Droid/res/drawable-xxxhdpi/ic_refresh_white.png index fe0ae13aa..f5beca251 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_refresh_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_refresh_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_search_white.png b/F-Droid/res/drawable-xxxhdpi/ic_search_white.png index 7caf6c9b7..dd5adfc7f 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_search_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_search_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_settings_white.png b/F-Droid/res/drawable-xxxhdpi/ic_settings_white.png index 4d36a012e..507c5edd4 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_settings_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_settings_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_share_white.png b/F-Droid/res/drawable-xxxhdpi/ic_share_white.png index 4eeff94cf..e351c7beb 100644 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_share_white.png and b/F-Droid/res/drawable-xxxhdpi/ic_share_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_toc_white.png b/F-Droid/res/drawable-xxxhdpi/ic_toc_white.png new file mode 100644 index 000000000..0ec6e3895 Binary files /dev/null and b/F-Droid/res/drawable-xxxhdpi/ic_toc_white.png differ diff --git a/F-Droid/res/drawable-xxxhdpi/ic_view_headline_white.png b/F-Droid/res/drawable-xxxhdpi/ic_view_headline_white.png deleted file mode 100644 index 7674b081f..000000000 Binary files a/F-Droid/res/drawable-xxxhdpi/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/hotspot.png b/F-Droid/res/drawable/hotspot.png deleted file mode 100644 index 88953cea6..000000000 Binary files a/F-Droid/res/drawable/hotspot.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_add_white.png b/F-Droid/res/drawable/ic_add_white.png deleted file mode 100644 index 67042105d..000000000 Binary files a/F-Droid/res/drawable/ic_add_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_bluetooth_white.png b/F-Droid/res/drawable/ic_bluetooth_white.png deleted file mode 100644 index 678678da4..000000000 Binary files a/F-Droid/res/drawable/ic_bluetooth_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_delete_white.png b/F-Droid/res/drawable/ic_delete_white.png deleted file mode 100644 index cdb230c2f..000000000 Binary files a/F-Droid/res/drawable/ic_delete_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_do_not_disturb_white.png b/F-Droid/res/drawable/ic_do_not_disturb_white.png deleted file mode 100644 index 4e4fa1e59..000000000 Binary files a/F-Droid/res/drawable/ic_do_not_disturb_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_edit_white.png b/F-Droid/res/drawable/ic_edit_white.png deleted file mode 100644 index 7f0ea51bf..000000000 Binary files a/F-Droid/res/drawable/ic_edit_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_help_white.png b/F-Droid/res/drawable/ic_help_white.png deleted file mode 100644 index 9f8051b44..000000000 Binary files a/F-Droid/res/drawable/ic_help_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_nfc_white.png b/F-Droid/res/drawable/ic_nfc_white.png deleted file mode 100644 index 428351e8e..000000000 Binary files a/F-Droid/res/drawable/ic_nfc_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_play_arrow_white.png b/F-Droid/res/drawable/ic_play_arrow_white.png deleted file mode 100644 index a55d19922..000000000 Binary files a/F-Droid/res/drawable/ic_play_arrow_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_refresh_white.png b/F-Droid/res/drawable/ic_refresh_white.png deleted file mode 100644 index 5f89fc257..000000000 Binary files a/F-Droid/res/drawable/ic_refresh_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_search_white.png b/F-Droid/res/drawable/ic_search_white.png deleted file mode 100644 index 043759acd..000000000 Binary files a/F-Droid/res/drawable/ic_search_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_settings_white.png b/F-Droid/res/drawable/ic_settings_white.png deleted file mode 100644 index 12e5d100d..000000000 Binary files a/F-Droid/res/drawable/ic_settings_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_share_white.png b/F-Droid/res/drawable/ic_share_white.png deleted file mode 100644 index dd536bca2..000000000 Binary files a/F-Droid/res/drawable/ic_share_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_swap.png b/F-Droid/res/drawable/ic_swap.png deleted file mode 100644 index 01e501ea8..000000000 Binary files a/F-Droid/res/drawable/ic_swap.png and /dev/null differ diff --git a/F-Droid/res/drawable/ic_text_dot.xml b/F-Droid/res/drawable/ic_text_dot.xml deleted file mode 100644 index f8f396453..000000000 --- a/F-Droid/res/drawable/ic_text_dot.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The Android Open Source Project - - 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. ---> -<inset xmlns:android="http://schemas.android.com/apk/res/android" - android:inset="10dp"> - <shape android:shape="oval"> - <solid android:color="?android:attr/textColorSecondary" /> - <size android:width="4dp" android:height="4dp" /> - </shape> -</inset> diff --git a/F-Droid/res/drawable/ic_view_headline_white.png b/F-Droid/res/drawable/ic_view_headline_white.png deleted file mode 100644 index e6ecf5a1d..000000000 Binary files a/F-Droid/res/drawable/ic_view_headline_white.png and /dev/null differ diff --git a/F-Droid/res/drawable/nfc_touch.png b/F-Droid/res/drawable/nfc_touch.png deleted file mode 100644 index d24a29e1c..000000000 Binary files a/F-Droid/res/drawable/nfc_touch.png and /dev/null differ diff --git a/F-Droid/res/drawable/swap_nfc_icon.png b/F-Droid/res/drawable/swap_nfc_icon.png deleted file mode 100644 index d11ac74f6..000000000 Binary files a/F-Droid/res/drawable/swap_nfc_icon.png and /dev/null differ diff --git a/F-Droid/res/drawable/swap_success.png b/F-Droid/res/drawable/swap_success.png deleted file mode 100644 index 1d09bfd42..000000000 Binary files a/F-Droid/res/drawable/swap_success.png and /dev/null differ diff --git a/F-Droid/res/drawable/wifi.png b/F-Droid/res/drawable/wifi.png deleted file mode 100644 index d2769efb1..000000000 Binary files a/F-Droid/res/drawable/wifi.png and /dev/null differ diff --git a/F-Droid/res/drawable/wifi_ap_personal.png b/F-Droid/res/drawable/wifi_ap_personal.png deleted file mode 100644 index 56f3216cf..000000000 Binary files a/F-Droid/res/drawable/wifi_ap_personal.png and /dev/null differ diff --git a/F-Droid/res/drawable/wifi_ap_private.png b/F-Droid/res/drawable/wifi_ap_private.png deleted file mode 100644 index 62fc961fc..000000000 Binary files a/F-Droid/res/drawable/wifi_ap_private.png and /dev/null differ diff --git a/F-Droid/res/drawable/wifi_ap_public.png b/F-Droid/res/drawable/wifi_ap_public.png deleted file mode 100644 index 2eef507b8..000000000 Binary files a/F-Droid/res/drawable/wifi_ap_public.png and /dev/null differ diff --git a/F-Droid/res/layout/about.xml b/F-Droid/res/layout/about.xml index 909a8518d..671e6153e 100644 --- a/F-Droid/res/layout/about.xml +++ b/F-Droid/res/layout/about.xml @@ -2,12 +2,11 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:paddingLeft="8dp" - android:paddingStart="8dp" - android:paddingRight="8dp" - android:paddingEnd="8dp" - android:paddingTop="6dp" - android:paddingBottom="6dp" + android:paddingLeft="24dp" + android:paddingStart="24dp" + android:paddingRight="24dp" + android:paddingEnd="24dp" + android:paddingTop="20dp" android:baselineAligned="false" android:orientation="vertical"> diff --git a/F-Droid/res/layout/addrepo.xml b/F-Droid/res/layout/addrepo.xml index d94d86a20..c9d2d6522 100644 --- a/F-Droid/res/layout/addrepo.xml +++ b/F-Droid/res/layout/addrepo.xml @@ -3,7 +3,11 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="6dp"> + android:paddingLeft="24dp" + android:paddingStart="24dp" + android:paddingRight="24dp" + android:paddingEnd="24dp" + android:paddingTop="20dp"> <LinearLayout android:id="@+id/add_repo_form" diff --git a/F-Droid/res/layout/app_details_header.xml b/F-Droid/res/layout/app_details_header.xml index e36319c54..99f2cb936 100644 --- a/F-Droid/res/layout/app_details_header.xml +++ b/F-Droid/res/layout/app_details_header.xml @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/icon_and_title" android:layout_width="match_parent" @@ -40,6 +40,7 @@ android:layout_gravity="center_vertical" android:baselineAligned="false" android:orientation="vertical" + android:layout_toRightOf="@id/icon" android:paddingLeft="16dp" android:paddingStart="16dp"> @@ -109,7 +110,50 @@ </LinearLayout> </LinearLayout> -</LinearLayout> + <LinearLayout + android:id="@+id/holder" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/icon" + android:gravity="center"> + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1"> + <ProgressBar + android:id="@+id/progress_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal" /> + <TextView + android:id="@+id/progress_size" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_alignParentLeft="true" + android:layout_below="@id/progress_bar" + android:textSize="12sp"/> + <TextView + android:id="@+id/progress_percentage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_below="@id/progress_bar" + android:textSize="12sp"/> + </RelativeLayout> + <ImageButton + android:id="@+id/cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:layout_weight="0" + android:visibility="gone" + android:src="@drawable/ic_clear" + android:background="@null"/> + </LinearLayout> +</RelativeLayout> diff --git a/F-Droid/res/layout/app_permission_item_old.xml b/F-Droid/res/layout/app_permission_item_old.xml deleted file mode 100644 index a5b395ede..000000000 --- a/F-Droid/res/layout/app_permission_item_old.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project - - 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. ---> - -<!-- - Defines the layout of a single permission item. - Contains the group name and a list of permission labels under the group. ---> - -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/perm_icon" - android:layout_width="24dip" - android:layout_height="24dip" - android:layout_alignParentStart="true" - android:scaleType="fitCenter" /> - - - <TextView - android:id="@+id/permission_group" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textStyle="bold" - android:paddingStart="6dip" - android:layout_toEndOf="@id/perm_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/permission_list" - android:textAppearance="?android:attr/textAppearanceSmall" - android:layout_marginTop="-4dip" - android:paddingBottom="8dip" - android:paddingStart="6dip" - android:layout_below="@id/permission_group" - android:layout_toEndOf="@id/perm_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - -</RelativeLayout> diff --git a/F-Droid/res/layout/appinfo.xml b/F-Droid/res/layout/appinfo.xml deleted file mode 100644 index 389acf75b..000000000 --- a/F-Droid/res/layout/appinfo.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:paddingTop="4dp" - android:paddingBottom="8dp" - android:baselineAligned="false" - android:orientation="vertical" > - - <TextView - android:id="@+id/summary" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textStyle="bold" /> - - <TextView - android:id="@+id/appid" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textSize="12sp" /> - - <TextView - android:id="@+id/signature" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textSize="12sp" /> - - <TextView - android:id="@+id/antifeatures" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginTop="6sp" - android:textStyle="bold" - android:textColor="#ff0000" /> - - <TextView - android:id="@+id/description" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8sp" - android:textSize="13sp" - android:singleLine="false" /> - - <TextView - android:id="@+id/permissions" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8sp" - android:singleLine="true" - android:textStyle="bold" /> - - <TextView - android:id="@+id/permissions_list" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textSize="13sp" - android:singleLine="false" /> - -</LinearLayout> diff --git a/F-Droid/res/layout/local_repo_activity.xml b/F-Droid/res/layout/local_repo_activity.xml deleted file mode 100644 index d7a8a6045..000000000 --- a/F-Droid/res/layout/local_repo_activity.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - - <Button - android:id="@+id/enable_wifi" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/enable_wifi" /> - - <CheckBox - android:id="@+id/repoSwitch" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center" - android:padding="15dp" - android:text="@string/touch_to_turn_on_local_repo" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:text="@string/sharing_uri" /> - - <TextView - android:id="@+id/sharing_uri" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginLeft="15dp" - android:layout_marginStart="15dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textStyle="bold" - android:typeface="monospace" /> - </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:text="@string/wifi_network" /> - - <TextView - android:id="@+id/wifi_network" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginLeft="15dp" - android:layout_marginStart="15dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textStyle="bold" - android:typeface="monospace" /> - </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:text="@string/fingerprint" /> - - <TextView - android:id="@+id/fingerprint" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginLeft="15dp" - android:layout_marginStart="15dp" - android:typeface="monospace" /> - </LinearLayout> - - <TextView - android:id="@+id/instrucionsTextView" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="20dp" - android:layout_marginStart="20dp" - android:layout_marginRight="20dp" - android:layout_marginEnd="20dp" - android:text="@string/same_wifi_instructions" /> - - <ImageView - android:id="@+id/repoQrCode" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:contentDescription="@string/qr_content_description" /> - -</LinearLayout> diff --git a/F-Droid/res/layout/qr_wizard_activity.xml b/F-Droid/res/layout/qr_wizard_activity.xml deleted file mode 100644 index b461f9eb8..000000000 --- a/F-Droid/res/layout/qr_wizard_activity.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - - <TextView - android:id="@+id/qrWizardInstructions" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:text="@string/wifi_network" /> - - <TextView - android:id="@+id/qrWifiNetworkName" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginLeft="15dp" - android:layout_marginStart="15dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textStyle="bold" - android:typeface="monospace" /> - </LinearLayout> - - <ImageView - android:id="@+id/qrWizardImage" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:contentDescription="@string/qr_code" /> - - <Button - android:id="@+id/qrNextButton" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/next" /> - -</LinearLayout> diff --git a/F-Droid/res/layout/repodetails.xml b/F-Droid/res/layout/repodetails.xml index 86cb9b1a2..921612d11 100644 --- a/F-Droid/res/layout/repodetails.xml +++ b/F-Droid/res/layout/repodetails.xml @@ -1,32 +1,32 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout - android:layout_width="fill_parent" - android:layout_height="fill_parent" - xmlns:android="http://schemas.android.com/apk/res/android" - android:focusable="true" - android:focusableInTouchMode="true" +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" android:paddingTop="@dimen/padding_top" android:paddingLeft="@dimen/padding_side" android:paddingStart="@dimen/padding_side" android:paddingRight="@dimen/padding_side" android:paddingEnd="@dimen/padding_side"> - <!-- Editable URL of this repo --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RelativeLayout + android:id="@+id/repoView" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:id="@+id/label_repo_url" - android:text="@string/repo_url" - android:layout_alignParentLeft="true" - android:layout_alignParentStart="true" - android:layout_alignParentTop="true" /> - <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/input_repo_url" - android:inputType="textUri" - android:layout_below="@id/label_repo_url" /> + android:textStyle="bold" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" /> <!-- Name of this repo --> <TextView @@ -138,4 +138,12 @@ android:layout_height="wrap_content" android:layout_below="@id/text_not_yet_updated"/> -</RelativeLayout> + </RelativeLayout> + + <ImageView + android:id="@+id/qr_code" + android:src="@drawable/swap_qr_example" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </LinearLayout> +</ScrollView> diff --git a/F-Droid/res/layout/repodiscoverylist.xml b/F-Droid/res/layout/repodiscoverylist.xml index cdd85147d..694d07897 100644 --- a/F-Droid/res/layout/repodiscoverylist.xml +++ b/F-Droid/res/layout/repodiscoverylist.xml @@ -1,12 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" > + android:layout_height="match_parent" + android:paddingLeft="24dp" + android:paddingStart="24dp" + android:paddingRight="24dp" + android:paddingEnd="24dp" + android:paddingTop="20dp" > <LinearLayout android:id="@+id/reposcanprogresslayout" android:layout_width="match_parent" - android:layout_height="50dp" + android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" @@ -42,4 +47,4 @@ android:padding="8sp" /> -</RelativeLayout> \ No newline at end of file +</RelativeLayout> diff --git a/F-Droid/res/layout/repolisticons.xml b/F-Droid/res/layout/repolisticons.xml deleted file mode 100644 index 18cb61e24..000000000 --- a/F-Droid/res/layout/repolisticons.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/vw1" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <ImageView - android:id="@+id/img" - android:contentDescription="@string/repo_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - /> - - <LinearLayout - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <TextView android:id="@+id/uri" - android:textSize="21sp" - android:textStyle="bold" - android:singleLine="true" - android:ellipsize="marquee" - android:layout_width="fill_parent" - android:layout_height="fill_parent"/> - - <TextView android:id="@+id/fingerprint" - android:textSize="14sp" - android:typeface="monospace" - android:singleLine="false" - android:layout_width="fill_parent" - android:layout_height="fill_parent"/> - - </LinearLayout> - -</LinearLayout> -<!-- - * Copyright (C) 2009 Roberto Jacinto - * roberto.jacinto@caixamagica.pt - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ---> diff --git a/F-Droid/res/layout/swap_connecting.xml b/F-Droid/res/layout/swap_connecting.xml index e729653db..40dc308fb 100644 --- a/F-Droid/res/layout/swap_connecting.xml +++ b/F-Droid/res/layout/swap_connecting.xml @@ -30,6 +30,19 @@ tools:text="Downloading index from http://10.0.0.4:8888/fdroid/repo" android:padding="30dp" /> - <!-- TODO: Add button for "Retry" and show an error message when failed connecting. --> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/error" + android:text="@string/swap_connection_misc_error" + android:padding="30dp" + android:visibility="gone" /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/back" + android:text="@string/back" + android:visibility="gone" /> </org.fdroid.fdroid.views.swap.SwapConnecting> \ No newline at end of file diff --git a/F-Droid/res/menu/local_repo_activity.xml b/F-Droid/res/menu/local_repo_activity.xml deleted file mode 100644 index 606090278..000000000 --- a/F-Droid/res/menu/local_repo_activity.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" > - - <item - android:id="@+id/menu_setup_repo" - android:icon="@android:drawable/ic_input_add" - android:title="@string/setup_repo" - app:showAsAction="ifRoom|withText"/> - <item - android:id="@+id/menu_send_fdroid_via_wifi" - android:icon="@android:drawable/arrow_up_float" - android:title="@string/send_fdroid_via_wifi" - app:showAsAction="never"/> - <item - android:id="@+id/menu_settings" - android:icon="@android:drawable/ic_menu_preferences" - android:title="@string/menu_preferences" - app:showAsAction="never"/> - -</menu> \ No newline at end of file diff --git a/F-Droid/res/menu/main.xml b/F-Droid/res/menu/main.xml index b454adc54..9c8a76dc0 100644 --- a/F-Droid/res/menu/main.xml +++ b/F-Droid/res/menu/main.xml @@ -7,18 +7,13 @@ android:icon="@drawable/ic_search_white" android:title="@string/menu_search" app:showAsAction="always"/> - <item - android:id="@+id/action_update_repo" - android:icon="@drawable/ic_refresh_white" - android:title="@string/menu_update_repo" - app:showAsAction="ifRoom"/> <item android:id="@+id/action_swap" android:title="@string/swap" app:showAsAction="ifRoom"/> <item android:id="@+id/action_manage_repos" - android:icon="@drawable/ic_view_headline_white" + android:icon="@drawable/ic_toc_white" android:title="@string/menu_manage" app:showAsAction="ifRoom"/> <item @@ -26,6 +21,11 @@ android:icon="@drawable/ic_bluetooth_white" android:title="@string/menu_send_apk_bt" app:showAsAction="ifRoom"/> + <item + android:id="@+id/action_update_repo" + android:icon="@drawable/ic_refresh_white" + android:title="@string/menu_update_repo" + app:showAsAction="ifRoom"/> <item android:id="@+id/action_settings" android:icon="@drawable/ic_settings_white" @@ -37,4 +37,4 @@ android:title="@string/menu_about" app:showAsAction="ifRoom"/> -</menu> \ No newline at end of file +</menu> diff --git a/F-Droid/res/menu/manage_repo_context.xml b/F-Droid/res/menu/manage_repo_context.xml deleted file mode 100644 index 57506a395..000000000 --- a/F-Droid/res/menu/manage_repo_context.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<menu xmlns:android="http://schemas.android.com/apk/res/android"> - - <item - android:id="@+id/edit_repo" - android:title="@string/edit" - android:icon="@drawable/ic_edit_white" /> - - <item - android:id="@+id/delete_repo" - android:title="@string/delete" - android:icon="@drawable/ic_delete_white" /> - -</menu> \ No newline at end of file diff --git a/F-Droid/res/menu/repo_details_activity.xml b/F-Droid/res/menu/repo_details_activity.xml new file mode 100644 index 000000000..82a38938c --- /dev/null +++ b/F-Droid/res/menu/repo_details_activity.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <item + android:id="@+id/menu_update" + android:icon="@drawable/ic_refresh_white" + android:title="@string/repo_update" + app:showAsAction="always|withText" /> + <item + android:id="@+id/menu_delete" + android:icon="@drawable/ic_delete_white" + android:title="@string/delete" + app:showAsAction="ifRoom|withText" /> + <item + android:id="@+id/menu_enable_nfc" + android:icon="@drawable/ic_nfc_white" + android:title="@string/enable_nfc_send" + app:showAsAction="ifRoom|withText" /> + +</menu> \ No newline at end of file diff --git a/F-Droid/res/menu/select_local_apps_action_mode.xml b/F-Droid/res/menu/select_local_apps_action_mode.xml deleted file mode 100644 index f0c9bc6f1..000000000 --- a/F-Droid/res/menu/select_local_apps_action_mode.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" > - - <item - android:id="@+id/action_search" - android:icon="@android:drawable/ic_menu_search" - android:title="@string/menu_search" - app:actionViewClass="android.support.v7.widget.SearchView" - app:showAsAction="ifRoom"/> - <item - android:id="@+id/action_update_repo" - android:icon="@android:drawable/ic_input_add" - android:title="@string/update_repo" - app:showAsAction="always"/> - -</menu> \ No newline at end of file diff --git a/F-Droid/res/menu/select_local_apps_activity.xml b/F-Droid/res/menu/select_local_apps_activity.xml deleted file mode 100644 index 172e907bf..000000000 --- a/F-Droid/res/menu/select_local_apps_activity.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" > - - <item - android:id="@+id/action_search" - android:icon="@android:drawable/ic_menu_search" - android:title="@string/menu_search" - app:actionViewClass="android.support.v7.widget.SearchView" - app:showAsAction="collapseActionView|always"/> - <item - android:id="@+id/action_settings" - android:icon="@android:drawable/ic_menu_preferences" - android:title="@string/menu_preferences" - app:showAsAction="ifRoom"/> - -</menu> \ No newline at end of file diff --git a/F-Droid/res/values-ca/strings.xml b/F-Droid/res/values-ca/strings.xml index 7851230ea..ece623ba0 100644 --- a/F-Droid/res/values-ca/strings.xml +++ b/F-Droid/res/values-ca/strings.xml @@ -44,7 +44,6 @@ L\'adreça d\'un dipòsit té un aspecte com ara: https://f-droid.org/repo</stri <string name="enable">Permès</string> <string name="add_key">Afegeix clau</string> <string name="overwrite">Sobreescriu</string> - <string name="repo_delete_title">Trieu el dipòsit que voleu suprimir</string> <string name="repo_update_title">Actualitza els dipòsits</string> <string name="tab_noninstalled">Disponible</string> <string name="tab_updates">Actualitzacions</string> @@ -104,7 +103,6 @@ La voleu actualitzar?</string> <string name="status_checking_compatibility">S\'està comprovant la compatibilitat de les aplicacions amb el vostre dispositiu…</string> <string name="no_permissions">No es fa servir cap permís.</string> <string name="permissions_for_long">Permisos de la versió %s</string> - <string name="showPermissions">Mostra els permisos</string> <string name="no_handler_app">No teniu cap aplicació disponible que pugui gestionar %s</string> <string name="compactlayout">Vista compacta</string> <string name="theme">Tema</string> diff --git a/F-Droid/res/values-cs/strings.xml b/F-Droid/res/values-cs/strings.xml index e7dd4bef2..2a2f07eca 100644 --- a/F-Droid/res/values-cs/strings.xml +++ b/F-Droid/res/values-cs/strings.xml @@ -48,7 +48,6 @@ Uvolněno pod GPLv3 licencí.</string> <string name="enable">Povolit</string> <string name="add_key">Přidat klíč</string> <string name="overwrite">Přepsat</string> - <string name="repo_delete_title">Vybrat repozitář k odebrání</string> <string name="repo_update_title">Aktualizovat repozitáře</string> <string name="tab_noninstalled">Dostupné</string> <string name="tab_updates">Aktualizace</string> @@ -143,8 +142,6 @@ Uvolněno pod GPLv3 licencí.</string> <string name="global_error_updating_repos">Chyba při aktualizaci:</string> <string name="no_permissions">Žádná oprávnění nejsou použita.</string> <string name="permissions_for_long">Oprávnění pro verzi %s</string> - <string name="showPermissions">Zobrazit oprávnění</string> - <string name="showPermissions_on">Zobrazit seznam oprávnění požadovaný aplikací</string> <string name="compactlayout">Úsporné rozvržení</string> <string name="compactlayout_on">Zobrazit menší ikonky</string> <string name="theme">Téma</string> diff --git a/F-Droid/res/values-de/strings.xml b/F-Droid/res/values-de/strings.xml index 60e2881f4..440cddcce 100644 --- a/F-Droid/res/values-de/strings.xml +++ b/F-Droid/res/values-de/strings.xml @@ -58,7 +58,6 @@ Die Adresse einer Paketquelle könnte wie folgt aussehen: https://f-droid.org/re <string name="enable">Aktivieren</string> <string name="add_key">Schlüssel hinzufügen</string> <string name="overwrite">Überschreiben</string> - <string name="repo_delete_title">Zu entfernende Paketquelle auswählen</string> <string name="repo_update_title">Paketquellen aktualisieren</string> <string name="tab_noninstalled">Verfügbar</string> <string name="tab_updates">Aktualisierungen</string> @@ -179,8 +178,6 @@ wird verbunden</string> <string name="global_error_updating_repos">Fehler während der Aktualisierung:</string> <string name="no_permissions">Es werden keine Berechtigungen verwendet.</string> <string name="permissions_for_long">Berechtigungen für Version %s</string> - <string name="showPermissions">Berechtigungen anzeigen</string> - <string name="showPermissions_on">Eine Liste mit Berechtigungen, die von einer Anwendung verlangt werden, anzeigen</string> <string name="no_handler_app">Es ist keine Anwendung installiert, die mit %s umgehen kann</string> <string name="compactlayout">Kompakte Ansicht</string> <string name="compactlayout_on">Symbole in einer kleineren Größe anzeigen</string> diff --git a/F-Droid/res/values-el/strings.xml b/F-Droid/res/values-el/strings.xml index 1129a0120..9a4323044 100644 --- a/F-Droid/res/values-el/strings.xml +++ b/F-Droid/res/values-el/strings.xml @@ -51,7 +51,6 @@ <string name="enable">Ενεργοποίηση</string> <string name="add_key">Προσθήκη κλειδιού</string> <string name="overwrite">Αντικατάσταση</string> - <string name="repo_delete_title">Επιλογή αποθετηρίου για διαγραφή</string> <string name="repo_update_title">Ενημέρωση αποθετηρίων</string> <string name="tab_noninstalled">Διαθέσιμα</string> <string name="tab_updates">Ενημερώσεις</string> @@ -130,8 +129,6 @@ <string name="status_inserting">Αποθήκευση λεπτομερειών των εφαρμογών</string> <string name="no_permissions">Δεν χρησιμοποιείται καμία άδεια.</string> <string name="permissions_for_long">Άδειες για την έκδοση %s</string> - <string name="showPermissions">Εμφάνιση αδειών</string> - <string name="showPermissions_on">Εμφάνιση μιας λίστας με τις άδειες που απαιτεί η εφαρμογή</string> <string name="no_handler_app">Δεν έχεται καμία διαθέσιμη εφαρμογή που να μπορεί να χειριστεί %s</string> <string name="compactlayout">Συμπτυγμένη Διάταξη</string> <string name="compactlayout_on">Εμφάνιση εικονιδίων σε μικρότερο μέγεθος</string> diff --git a/F-Droid/res/values-es/strings.xml b/F-Droid/res/values-es/strings.xml index 3fd280b3f..57e18ea72 100644 --- a/F-Droid/res/values-es/strings.xml +++ b/F-Droid/res/values-es/strings.xml @@ -57,7 +57,6 @@ La dirección de un repositorio es algo similar a esto: https://f-droid.org/repo <string name="enable">Habilitar</string> <string name="add_key">Añadir clave</string> <string name="overwrite">Sobreescribir</string> - <string name="repo_delete_title">Elige el repositorio a eliminar</string> <string name="repo_update_title">Actualizar repositorios</string> <string name="tab_noninstalled">Disponible</string> <string name="tab_updates">Actualizaciones</string> @@ -178,8 +177,6 @@ La dirección de un repositorio es algo similar a esto: https://f-droid.org/repo <string name="global_error_updating_repos">Error en la Actualización:</string> <string name="no_permissions">No se usan permisos.</string> <string name="permissions_for_long">Permisos para la versión %s</string> - <string name="showPermissions">Mostrar permisos</string> - <string name="showPermissions_on">Mostrar una lista de los permisos que requiere una aplicación</string> <string name="no_handler_app">No tienes instalada ninguna aplicación que pueda manejar %s</string> <string name="compactlayout">Diseño compacto</string> <string name="compactlayout_on">Mostrar iconos en tamaño menor</string> diff --git a/F-Droid/res/values-eu/strings.xml b/F-Droid/res/values-eu/strings.xml index 645347278..1e5182296 100644 --- a/F-Droid/res/values-eu/strings.xml +++ b/F-Droid/res/values-eu/strings.xml @@ -40,7 +40,6 @@ GNU GPLv3 lizentziapean argitaratua.</string> <string name="enable">Gaitu</string> <string name="add_key">Gehitu gakoa</string> <string name="overwrite">Gainidatzi</string> - <string name="repo_delete_title">Aukeratu biltegia ezabatzeko</string> <string name="repo_update_title">Eguneratu biltegiak</string> <string name="tab_noninstalled">Eskuragarri</string> <string name="tab_updates">Eguneraketak</string> @@ -96,7 +95,6 @@ konektatzen</string> <string name="status_checking_compatibility">Aplikazioak zure gailuarekin bateragarriak diren egiaztatzen…</string> <string name="no_permissions">Ez da baimenik erabiltzen.</string> <string name="permissions_for_long">%s bertsioarentzako baimenak</string> - <string name="showPermissions">Erakutsi baimenak</string> <string name="compactlayout">Diseinu trinkoa</string> <string name="theme">Gaia</string> <string name="unsigned">Sinatu gabea</string> diff --git a/F-Droid/res/values-fa/strings.xml b/F-Droid/res/values-fa/strings.xml index 4474ab384..9ad98b117 100644 --- a/F-Droid/res/values-fa/strings.xml +++ b/F-Droid/res/values-fa/strings.xml @@ -38,7 +38,6 @@ <string name="enable">توانا ساختن</string> <string name="add_key">فزودن کلید</string> <string name="overwrite">بازنویسی</string> - <string name="repo_delete_title">انتخاب مخزن برای حذف</string> <string name="repo_update_title">بهروزرسانی مخازن</string> <string name="tab_updates">بهروزرسانیها</string> <string name="fdroid_updates_available">بهروزرسانیهای F-Droid موجود هستند</string> @@ -87,8 +86,6 @@ %1$s</string> <string name="status_checking_compatibility">بررسی سازگاری برنامهها با دستگاه شما…</string> <string name="no_permissions">دسترسیای استفاده نشدهاست.</string> - <string name="showPermissions">نمایش دسترسیها</string> - <string name="showPermissions_on">نمایش یک فهرست از دسترسیهایی که یک برنامه نیاز دارد</string> <string name="compactlayout">طرحبندی فشرده</string> <string name="compactlayout_on">نمایش شکلکها در اندازه کوچکتر</string> <string name="theme">پوسته</string> diff --git a/F-Droid/res/values-fi/strings.xml b/F-Droid/res/values-fi/strings.xml index 0ce2a9616..177cbaa8a 100644 --- a/F-Droid/res/values-fi/strings.xml +++ b/F-Droid/res/values-fi/strings.xml @@ -49,7 +49,6 @@ <string name="enable">Ota käyttöön</string> <string name="add_key">Lisää avain</string> <string name="overwrite">Korvaa</string> - <string name="repo_delete_title">Valitse sovelluslähde, jonka tahdot poistaa</string> <string name="repo_update_title">Päivitä sovelluslähteet</string> <string name="tab_noninstalled">Saatavilla</string> <string name="tab_updates">Päivityksiä</string> @@ -142,7 +141,6 @@ Tahdotko päivittää ne?</string> <string name="repos_unchanged">Yhdessäkään säilössä ei ole pakettipäivityksiä</string> <string name="all_other_repos_fine">Muut säilöt eivät luoneet virheitä.</string> <string name="global_error_updating_repos">Päivityksenaikainen virhe:</string> - <string name="showPermissions">Näytä oikeudet</string> <string name="theme">Teema</string> <string name="unverified">Vahvistamaton</string> <string name="repo_not_yet_updated">Tätä säilöä ei ole vielä käytetty. diff --git a/F-Droid/res/values-fr/strings.xml b/F-Droid/res/values-fr/strings.xml index 9cf626580..08533f61c 100644 --- a/F-Droid/res/values-fr/strings.xml +++ b/F-Droid/res/values-fr/strings.xml @@ -54,7 +54,6 @@ L\'adresse d\'un dépôt ressemble à ceci: https://f-droid.org/repo</string> <string name="enable">Activer</string> <string name="add_key">Ajouter une clé</string> <string name="overwrite">Écraser</string> - <string name="repo_delete_title">Choisissez le dépôt à supprimer</string> <string name="repo_update_title">Mettre à jour les dépôts</string> <string name="tab_noninstalled">Disponibles</string> <string name="tab_updates">Mises à jour</string> @@ -175,8 +174,6 @@ Voulez-vous les mettre à jour?</string> <string name="global_error_updating_repos">Erreur durant la mise à jour:</string> <string name="no_permissions">Aucune autorisation n\'est utilisée.</string> <string name="permissions_for_long">Permissions pour la version %s</string> - <string name="showPermissions">Afficher les permissions</string> - <string name="showPermissions_on">Afficher la liste des permissions qu\'une app requiert</string> <string name="no_handler_app">Vous n\'avez aucune application installée pour gérer %s</string> <string name="compactlayout">Affichage compact</string> <string name="compactlayout_on">Montrer les icônes à une taille plus petite</string> diff --git a/F-Droid/res/values-gl/strings.xml b/F-Droid/res/values-gl/strings.xml index c4e3032ea..b499edfef 100644 --- a/F-Droid/res/values-gl/strings.xml +++ b/F-Droid/res/values-gl/strings.xml @@ -43,7 +43,6 @@ Un enderezo a un repositorio sería algo <string name="repo_add_title">Engadir un novo repositorio</string> <string name="repo_add_add">Engadir</string> <string name="cancel">Cancelar</string> - <string name="repo_delete_title">Escoller o repositorio que retirar</string> <string name="repo_update_title">Actualizar repositorios</string> <string name="tab_noninstalled">Dispoñíbel</string> <string name="tab_updates">Actualizacións</string> @@ -101,7 +100,6 @@ Quere actualizalos?</string> <string name="status_checking_compatibility">Comprobando a compatibilidade das aps con seu aparello</string> <string name="no_permissions">Non se usan permisos</string> <string name="permissions_for_long">Permisos para a versión %s</string> - <string name="showPermissions">Amosar permisos</string> <string name="no_handler_app">Non ten ningunha ap dispoñíbel que poida manexar %s</string> <string name="compactlayout">Deseño compacto</string> <string name="theme">Tema</string> diff --git a/F-Droid/res/values-hu/strings.xml b/F-Droid/res/values-hu/strings.xml index 59f1f864b..2d566d0f4 100644 --- a/F-Droid/res/values-hu/strings.xml +++ b/F-Droid/res/values-hu/strings.xml @@ -50,7 +50,6 @@ A repo cím valahogy így néz ki: https://f-droid.org/repo\"</string> <string name="enable">Engedélyez</string> <string name="add_key">Kulcs hozzáadás</string> <string name="overwrite">Felülírás</string> - <string name="repo_delete_title">Válasszon ki repo-t az eltávolításhoz</string> <string name="repo_update_title">Repo-k frissítése</string> <string name="tab_noninstalled">Elérhető</string> <string name="tab_updates">Frissítések</string> @@ -119,8 +118,6 @@ Szeretné ezeket frissíteni?\"</string> <string name="status_checking_compatibility">Alkalmazások eszközkompatibilitási ellenőrzése…</string> <string name="no_permissions">Nincsenek engedélyei.</string> <string name="permissions_for_long">Engedélyek erre a verzióra - %s</string> - <string name="showPermissions">Engedélyek megjelenítése</string> - <string name="showPermissions_on">Mutassa meg egy listában az app által igényelt engedélyeket</string> <string name="no_handler_app">\"Nincs semmilyen app, ami képes ezt kezelni %s\"</string> <string name="compactlayout">Kompakt elrendezés</string> <string name="compactlayout_on">Ikonok kisebb méretben</string> diff --git a/F-Droid/res/values-it/strings.xml b/F-Droid/res/values-it/strings.xml index ac80682cb..30639d2c5 100644 --- a/F-Droid/res/values-it/strings.xml +++ b/F-Droid/res/values-it/strings.xml @@ -57,7 +57,6 @@ Un indirizzo URL di esempio è: https://f-droid.org/repo</string> <string name="enable">Abilita</string> <string name="add_key">Aggiungi chiave</string> <string name="overwrite">Sovrascrivi</string> - <string name="repo_delete_title">Rimuovi repository</string> <string name="repo_update_title">Aggiorna i repository</string> <string name="tab_noninstalled">Disponibile</string> <string name="tab_updates">Aggiornamenti</string> @@ -178,8 +177,6 @@ Vuoi aggiornarlo?</string> <string name="global_error_updating_repos">Errore nell\'aggiornamento:</string> <string name="no_permissions">Non viene usata alcuna autorizzazione.</string> <string name="permissions_for_long">Autorizzazioni per la versione %s</string> - <string name="showPermissions">Mostra autorizzazioni</string> - <string name="showPermissions_on">Mostra l\'elenco dei permessi richiesti da un\'applicazione</string> <string name="no_handler_app">Non hai alcuna app disponibile che può gestire %s</string> <string name="compactlayout">Layout Compatto</string> <string name="compactlayout_on">Mostra le icone a dimensione ridotta</string> diff --git a/F-Droid/res/values-ja/strings.xml b/F-Droid/res/values-ja/strings.xml index 8125fdf8f..31bed2bca 100644 --- a/F-Droid/res/values-ja/strings.xml +++ b/F-Droid/res/values-ja/strings.xml @@ -59,7 +59,6 @@ GNU GPLv3 ライセンスに基づいてリリースされました.</string> <string name="enable">有効</string> <string name="add_key">キーを追加</string> <string name="overwrite">上書き</string> - <string name="repo_delete_title">削除するリポジトリを選択してください</string> <string name="repo_update_title">リポジトリを更新</string> <string name="tab_noninstalled">インストール可能</string> <string name="tab_updates">更新</string> @@ -180,8 +179,6 @@ GNU GPLv3 ライセンスに基づいてリリースされました.</string> <string name="global_error_updating_repos">更新中に問題発生:</string> <string name="no_permissions">使用される権限はありません。</string> <string name="permissions_for_long">バージョン %s の権限</string> - <string name="showPermissions">権限を表示</string> - <string name="showPermissions_on">アプリケーションが要求する権限リストを表示します</string> <string name="no_handler_app">取り扱うアプリケーションはありません %s</string> <string name="compactlayout">コンパクト・レイアウト</string> <string name="compactlayout_on">アイコンを小さいサイズで表示します</string> diff --git a/F-Droid/res/values-ko/strings.xml b/F-Droid/res/values-ko/strings.xml index 8b3eba2d6..96be92651 100644 --- a/F-Droid/res/values-ko/strings.xml +++ b/F-Droid/res/values-ko/strings.xml @@ -32,7 +32,6 @@ <string name="repo_add_title">새로운 저장소 추가</string> <string name="repo_add_add">추가</string> <string name="cancel">취소</string> - <string name="repo_delete_title">제거할 저장소 선택</string> <string name="repo_update_title">저장소 업데이트</string> <string name="tab_updates">업데이트</string> <string name="one_update_available">1개의 업데이트를 사용할 수 있습니다.</string> @@ -82,7 +81,6 @@ <string name="status_checking_compatibility">장치와 응용프로그램의 호환성 확인중…</string> <string name="no_permissions">사용된 권한이 없습니다.</string> <string name="permissions_for_long">%s 버전에 대한 권한</string> - <string name="showPermissions">권한 표시</string> <string name="no_handler_app">%s을(를) 처리할 수 있는 응용프로그램이 없습니다.</string> <string name="compactlayout">컴팩트 레이아웃</string> <string name="theme">테마</string> diff --git a/F-Droid/res/values-lt/strings.xml b/F-Droid/res/values-lt/strings.xml index 4a3300129..024f1c8ec 100644 --- a/F-Droid/res/values-lt/strings.xml +++ b/F-Droid/res/values-lt/strings.xml @@ -32,7 +32,6 @@ <string name="enable">Įjungti</string> <string name="add_key">Pridėti raktą</string> <string name="overwrite">Perrašyti</string> - <string name="repo_delete_title">Pasirinkite saugyklą, kurią pašalinti</string> <string name="repo_update_title">Atnaujinti saugyklas</string> <string name="tab_noninstalled">Prieinamos programos</string> <string name="tab_updates">Atnaujinimai</string> @@ -85,7 +84,6 @@ Ar norite atnaujinti %1$s</string> <string name="repos_unchanged">Įjungtose saugyklose nėra nieko naujo</string> <string name="global_error_updating_repos">Klaida naujinant:</string> - <string name="showPermissions">Rodyti reikalaujamus leidimus</string> <string name="theme">Tema</string> <string name="repo_num_apps">Programų kiekis</string> <string name="repo_description">Aprašymas</string> diff --git a/F-Droid/res/values-nb/strings.xml b/F-Droid/res/values-nb/strings.xml index 2c6a15001..221d80989 100644 --- a/F-Droid/res/values-nb/strings.xml +++ b/F-Droid/res/values-nb/strings.xml @@ -55,7 +55,6 @@ Lisensiert GNU GPLv3.</string> <string name="enable">Skru på</string> <string name="add_key">Legg til nøkkel</string> <string name="overwrite">Overskriv</string> - <string name="repo_delete_title">Velg pakkebrønnen du vil fjerne</string> <string name="repo_update_title">Oppdater registerne</string> <string name="tab_noninstalled">Tilgjengelig</string> <string name="tab_updates">Oppdateringer</string> @@ -172,8 +171,6 @@ Lisensiert GNU GPLv3.</string> <string name="global_error_updating_repos">Feil under oppdatering:</string> <string name="no_permissions">Krever ingen tillatelser.</string> <string name="permissions_for_long">Tillatelser for versjon %s</string> - <string name="showPermissions">Vis tillatelser</string> - <string name="showPermissions_on">Vis en liste over rettighetene en app krever</string> <string name="no_handler_app">Du har ingen tilgjengelige applikasjoner som kan håndtere %s</string> <string name="compactlayout">Kompakt layout</string> <string name="compactlayout_on">Vis ikoner i mindre størrelse</string> diff --git a/F-Droid/res/values-nl/strings.xml b/F-Droid/res/values-nl/strings.xml index 495cb9a79..3d7868cd6 100644 --- a/F-Droid/res/values-nl/strings.xml +++ b/F-Droid/res/values-nl/strings.xml @@ -54,7 +54,6 @@ Een bron-adres ziet er ongeveer <string name="enable">Activeer</string> <string name="add_key">Voeg sleutel toe</string> <string name="overwrite">Overschrijven</string> - <string name="repo_delete_title">Kies bron om te verwijderen</string> <string name="repo_update_title">Vernieuw bronnen</string> <string name="tab_noninstalled">Beschikbaar</string> <string name="tab_updates">Updates</string> @@ -130,8 +129,6 @@ Wilt u ze vernieuwen?</string> <string name="status_inserting">Applicatiedetails opslaan (%1$d%%)</string> <string name="no_permissions">Geen permissies worden gebruikt</string> <string name="permissions_for_long">Permissies voor versie %s</string> - <string name="showPermissions">Laat permissies zien</string> - <string name="showPermissions_on">Laat een lijst zien van benodigde permissies voor een app</string> <string name="no_handler_app">U hebt geen beschikbare app die %s kan verwerken</string> <string name="compactlayout">Compacte Layout</string> <string name="compactlayout_on">Iconen weergeven in klein formaat</string> diff --git a/F-Droid/res/values-pl/strings.xml b/F-Droid/res/values-pl/strings.xml index 11a25ba8f..2865801d8 100644 --- a/F-Droid/res/values-pl/strings.xml +++ b/F-Droid/res/values-pl/strings.xml @@ -134,8 +134,6 @@ Czy chcesz je zaktualizować?</string> <string name="all_other_repos_fine">Pozostałe repozytoria nie zgłosiły błędów.</string> <string name="global_error_updating_repos">Błąd podczas aktualizacji:</string> <string name="permissions_for_long">Uprawnienia dla wersji %s</string> - <string name="showPermissions">Wyświetl uprawnienia</string> - <string name="showPermissions_on">Wyświetl listę uprawnień wymaganych przez aplikację</string> <string name="no_handler_app">Nie masz żadnej dostępnej aplikacji, która może obsłużyć %s</string> <string name="compactlayout">Widok kompaktowy</string> <string name="compactlayout_on">Pokaż ikony w mniejszym rozmiarze</string> diff --git a/F-Droid/res/values-pt-rBR/strings.xml b/F-Droid/res/values-pt-rBR/strings.xml index e98cc525a..bcdcaac2d 100644 --- a/F-Droid/res/values-pt-rBR/strings.xml +++ b/F-Droid/res/values-pt-rBR/strings.xml @@ -45,7 +45,6 @@ Um endereço do repositório é algo similar a isto: https://f-droid.org/repo</s <string name="repo_add_title">Adicionar novo repositório</string> <string name="repo_add_add">Adicionar</string> <string name="cancel">Cancelar</string> - <string name="repo_delete_title">Escolha o repositório para remover</string> <string name="repo_update_title">Atualizar repositórios</string> <string name="tab_noninstalled">Disponível</string> <string name="tab_updates">Atualizações</string> @@ -145,7 +144,6 @@ Você deseja atualizá-los?</string> <string name="global_error_updating_repos">Erro durante a atualização:</string> <string name="no_permissions">Nenhuma permissão utilizada.</string> <string name="permissions_for_long">Permissões para a versão %s</string> - <string name="showPermissions">Mostrar permissões</string> <string name="no_handler_app">Você não tem aplicativo instalado que lide com %s</string> <string name="compactlayout">Leiaute compacto</string> <string name="theme">Tema</string> diff --git a/F-Droid/res/values-ro/strings.xml b/F-Droid/res/values-ro/strings.xml index 2ff95a46c..71bf5cfd0 100644 --- a/F-Droid/res/values-ro/strings.xml +++ b/F-Droid/res/values-ro/strings.xml @@ -28,7 +28,6 @@ Distribuit sub licenta GNU GPLv3.</string> <string name="repo_add_add">Adauga</string> <string name="cancel">Anuleaza</string> <string name="enable">Activează</string> - <string name="repo_delete_title">Alegeti depozitul pentru stergere</string> <string name="repo_update_title">Actualizare depozit aplicatii</string> <string name="tab_noninstalled">Disponibil</string> <string name="tab_updates">Actualizare</string> @@ -55,7 +54,6 @@ Distribuit sub licenta GNU GPLv3.</string> <string name="category_all">Tot</string> <string name="category_whatsnew">Ce este nou</string> <string name="category_recentlyupdated">Actualizat recent</string> - <string name="showPermissions">Arată permisiunile</string> <string name="theme">Temă</string> <string name="repo_url">URL</string> <string name="repo_num_apps">Număr de aplicaţii</string> diff --git a/F-Droid/res/values-ru/strings.xml b/F-Droid/res/values-ru/strings.xml index 86c952d51..45c77c90c 100644 --- a/F-Droid/res/values-ru/strings.xml +++ b/F-Droid/res/values-ru/strings.xml @@ -59,7 +59,6 @@ <string name="enable">Включить</string> <string name="add_key">Добавить ключ</string> <string name="overwrite">Перезаписать</string> - <string name="repo_delete_title">Удалить репозиторий</string> <string name="repo_update_title">Обновить репозитории</string> <string name="tab_noninstalled">Доступно</string> <string name="tab_updates">Обновления</string> @@ -179,8 +178,6 @@ <string name="global_error_updating_repos">Ошибка во время обновления:</string> <string name="no_permissions">Разрешений не требуется.</string> <string name="permissions_for_long">Разрешения для версии %s</string> - <string name="showPermissions">Показывать разрешения</string> - <string name="showPermissions_on">Отображение списка разрешений, которые требуются приложению</string> <string name="no_handler_app">У вас нет установленного приложения для обработки %s</string> <string name="compactlayout">Компактный вид</string> <string name="compactlayout_on">Показать иконки в меньшем размере</string> diff --git a/F-Droid/res/values-sl/strings.xml b/F-Droid/res/values-sl/strings.xml index 6d83a3572..f72decdb7 100644 --- a/F-Droid/res/values-sl/strings.xml +++ b/F-Droid/res/values-sl/strings.xml @@ -23,7 +23,6 @@ Izdan z licenco GNU GPLv3.</string> <string name="repo_add_title">Dodaj novo skladišče</string> <string name="repo_add_add">Dodaj</string> <string name="cancel">Prekliči</string> - <string name="repo_delete_title">Odstrani skladišče</string> <string name="repo_update_title">Posodobi skladišča</string> <string name="tab_noninstalled">Na razpolago</string> <string name="tab_updates">Posodobitve</string> diff --git a/F-Droid/res/values-sr/strings.xml b/F-Droid/res/values-sr/strings.xml index c8b85e627..a7c4e99ef 100644 --- a/F-Droid/res/values-sr/strings.xml +++ b/F-Droid/res/values-sr/strings.xml @@ -58,7 +58,6 @@ <string name="enable">Омогући</string> <string name="add_key">Додај кључ</string> <string name="overwrite">Пребриши</string> - <string name="repo_delete_title">Изаберите ризницу за уклањање</string> <string name="repo_update_title">Ажурирај ризнице</string> <string name="tab_noninstalled">Доступно</string> <string name="tab_updates">Надоградње</string> @@ -179,8 +178,6 @@ <string name="global_error_updating_repos">Грешка приликом ажурирања:</string> <string name="no_permissions">Не захтевају се никакве дозволе.</string> <string name="permissions_for_long">Дозволе за издање %s</string> - <string name="showPermissions">Прикажи дозволе</string> - <string name="showPermissions_on">Прикажи списак дозвола које апликација захтева</string> <string name="no_handler_app">Немате инсталирану апликацију за %s</string> <string name="compactlayout">Компактни распоред</string> <string name="compactlayout_on">Прикажи иконе мање величине</string> diff --git a/F-Droid/res/values-sv/strings.xml b/F-Droid/res/values-sv/strings.xml index 894bde6f9..c54c98905 100644 --- a/F-Droid/res/values-sv/strings.xml +++ b/F-Droid/res/values-sv/strings.xml @@ -57,7 +57,6 @@ En förrådsadress ser ut så här: https://f-droid.org/repo</string> <string name="enable">Aktivera</string> <string name="add_key">Lägg till nyckel</string> <string name="overwrite">Skriv över</string> - <string name="repo_delete_title">Välj förråd att ta bort</string> <string name="repo_update_title">Uppdatera förråd</string> <string name="tab_noninstalled">Tillgängliga</string> <string name="tab_updates">Uppdateringar</string> @@ -178,8 +177,6 @@ Vill du uppdatera dem?</string> <string name="global_error_updating_repos">Fel under uppdatering:</string> <string name="no_permissions">Inga behörigheter används.</string> <string name="permissions_for_long">Behörigheter för version %s</string> - <string name="showPermissions">Visa behörigheter</string> - <string name="showPermissions_on">Visa en lista över behörigheter en app behöver</string> <string name="no_handler_app">Du har inte någon app tillgänglig för hantering av %s</string> <string name="compactlayout">Kompakt layout</string> <string name="compactlayout_on">Visa ikoner i en mindre storlek</string> diff --git a/F-Droid/res/values-tr/strings.xml b/F-Droid/res/values-tr/strings.xml index 405ac04a5..42ba57953 100644 --- a/F-Droid/res/values-tr/strings.xml +++ b/F-Droid/res/values-tr/strings.xml @@ -54,7 +54,6 @@ Bir depo adresi şuna benzer: https://f-droid.org/repo</string> <string name="enable">Etkinleştir</string> <string name="add_key">Anahtar ekle</string> <string name="overwrite">Üzerine yaz</string> - <string name="repo_delete_title">Kaldırılacak depoyu seç</string> <string name="repo_update_title">Depoları güncelle</string> <string name="tab_noninstalled">Mevcut</string> <string name="tab_updates">Güncellemeler</string> @@ -159,8 +158,6 @@ bağlanılıyor</string> <string name="status_inserting">Uygulama detayları kaydediliyor (%1$d%%)</string> <string name="no_permissions">Hiçbir izin kullanılmıyor.</string> <string name="permissions_for_long">%s sürümü için izinler</string> - <string name="showPermissions">İzinleri göster</string> - <string name="showPermissions_on">Uygulamaların gerektirdiği izinlerin listesini göster</string> <string name="no_handler_app">%s unsurunu yönetecek hiçbir mevcut uygulamanız yok</string> <string name="compactlayout">Yoğun düzen</string> <string name="compactlayout_on">İkonları daha küçük boyutta görüntüle</string> diff --git a/F-Droid/res/values-ug/strings.xml b/F-Droid/res/values-ug/strings.xml index 0cf70f83d..a2ab7d593 100644 --- a/F-Droid/res/values-ug/strings.xml +++ b/F-Droid/res/values-ug/strings.xml @@ -39,7 +39,6 @@ <string name="repo_add_title">يېڭى خەزىنە قوش</string> <string name="repo_add_add">قوش</string> <string name="cancel">ۋاز كەچ</string> - <string name="repo_delete_title">چىقىرىۋېتىدىغان خەزىنەنى تاللاڭ</string> <string name="repo_update_title">خەزىنە يېڭىلا</string> <string name="tab_noninstalled">ئىشلىتىشچان</string> <string name="tab_updates">يېڭىلانمىلار</string> @@ -97,7 +96,6 @@ <string name="status_checking_compatibility">ئەپلەرنىڭ ئۈسكۈنىڭىز بىلەن ماسلىشىشچانلىقىنى تەكشۈرۈۋاتىدۇ…</string> <string name="no_permissions">ھېچقانداق ھوقۇق ئىشلەتمەيدۇ.</string> <string name="permissions_for_long">%s نەشرىنىڭ ھوقۇقلىرى</string> - <string name="showPermissions">ھوقۇقلارنى كۆرسەت</string> <string name="no_handler_app">سىز %s نى بىر تەرەپ قىلالايدىغان ھېچقانداق ئەپ ئورناتمىغان</string> <string name="compactlayout">ئىخچام جايلاشتۇرۇش</string> <string name="theme">ئۆرنەك</string> diff --git a/F-Droid/res/values-uk/strings.xml b/F-Droid/res/values-uk/strings.xml index 73322fe72..be511cdc3 100644 --- a/F-Droid/res/values-uk/strings.xml +++ b/F-Droid/res/values-uk/strings.xml @@ -23,7 +23,6 @@ <string name="repo_add_title">Новий репозиторій</string> <string name="repo_add_add">Додати</string> <string name="cancel">Назад</string> - <string name="repo_delete_title">Видалити репозиторій</string> <string name="repo_update_title">Оновити репозиторії?</string> <string name="tab_noninstalled">Наявне</string> <string name="tab_updates">Оновлення</string> diff --git a/F-Droid/res/values-v11/styles.xml b/F-Droid/res/values-v11/styles.xml index 1b9ea4093..7e19f4d8a 100644 --- a/F-Droid/res/values-v11/styles.xml +++ b/F-Droid/res/values-v11/styles.xml @@ -5,4 +5,14 @@ <item name="android:actionButtonStyle">@style/SwapTheme.Wizard.ActionButton</item> </style> -</resources> \ No newline at end of file + <style name="AlertDialogBaseThemeDark" parent="Theme.AppCompat.Dialog.Alert"> + <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item> + <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item> + </style> + + <style name="AlertDialogBaseThemeLight" parent="Theme.AppCompat.Light.Dialog.Alert"> + <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item> + <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item> + </style> + +</resources> diff --git a/F-Droid/res/values-v21/styles.xml b/F-Droid/res/values-v21/styles.xml index 9b2ebc734..04093aaad 100644 --- a/F-Droid/res/values-v21/styles.xml +++ b/F-Droid/res/values-v21/styles.xml @@ -3,6 +3,7 @@ <style name="AppThemeDark" parent="AppBaseThemeDark"> <!-- customizations that are not API-level specific go here. --> + <item name="android:alertDialogTheme">@style/AlertDialogThemeDark</item> <item name="android:colorEdgeEffect">@color/fdroid_blue</item> <item name="android:colorControlActivated">@color/fdroid_green</item> <item name="android:colorControlHighlight">@color/fdroid_green</item> @@ -10,6 +11,7 @@ <style name="AppThemeLight" parent="AppBaseThemeLight"> <!-- customizations that are not API-level specific go here. --> + <item name="android:alertDialogTheme">@style/AlertDialogThemeLight</item> <item name="android:colorEdgeEffect">@color/fdroid_blue</item> </style> @@ -17,4 +19,4 @@ <item name="android:colorButtonNormal">#04b9e6</item> </style> -</resources> \ No newline at end of file +</resources> diff --git a/F-Droid/res/values-zh-rCN/strings.xml b/F-Droid/res/values-zh-rCN/strings.xml index d9cd34c5f..018c3fc78 100644 --- a/F-Droid/res/values-zh-rCN/strings.xml +++ b/F-Droid/res/values-zh-rCN/strings.xml @@ -54,7 +54,6 @@ https://f-droid.org/repo</string> <string name="enable">启用</string> <string name="add_key">添加密钥</string> <string name="overwrite">覆盖</string> - <string name="repo_delete_title">选择要移除的软件源</string> <string name="repo_update_title">更新软件源</string> <string name="tab_noninstalled">可安装</string> <string name="tab_updates">更新</string> @@ -146,8 +145,6 @@ https://f-droid.org/repo</string> <string name="status_inserting">正在保存应用程序的细节 (%1$d%%)</string> <string name="no_permissions">未使用任何权限。</string> <string name="permissions_for_long">版本 %s 的权限</string> - <string name="showPermissions">显示权限</string> - <string name="showPermissions_on">显示应用程序所需的权限清单</string> <string name="no_handler_app">你没有可处理 %s 的应用程序</string> <string name="compactlayout">紧凑布局</string> <string name="compactlayout_on">显示小图标</string> diff --git a/F-Droid/res/values-zh-rHK/strings.xml b/F-Droid/res/values-zh-rHK/strings.xml index d2926b696..eafcd2024 100644 --- a/F-Droid/res/values-zh-rHK/strings.xml +++ b/F-Droid/res/values-zh-rHK/strings.xml @@ -86,8 +86,6 @@ <string name="status_inserting">儲存應用程式詳情中(%1$d%%)</string> <string name="no_permissions">沒有使用任何存取權。</string> <string name="permissions_for_long">版本%s的存取權</string> - <string name="showPermissions">顯示存取權</string> - <string name="showPermissions_on">顯示應用程式所需的存取權</string> <string name="compactlayout">精簡設計</string> <string name="compactlayout_on">顯示小型圖示</string> <string name="theme">主題</string> diff --git a/F-Droid/res/values/strings.xml b/F-Droid/res/values/strings.xml index b009e5154..7a27fd60e 100644 --- a/F-Droid/res/values/strings.xml +++ b/F-Droid/res/values/strings.xml @@ -69,11 +69,11 @@ <string name="links">Links</string> <string name="content_description_view_more">View more</string> + <string name="back">Back</string> <string name="cancel">Cancel</string> <string name="enable">Enable</string> <string name="add_key">Add Key</string> <string name="overwrite">Overwrite</string> - <string name="repo_delete_title">Choose repository to remove</string> <string name="repo_update_title">Update repositories</string> <string name="tab_noninstalled">Available</string> @@ -209,6 +209,7 @@ - Percentage complete (int between 0-100) --> <string name="status_download">Downloading\n%2$s / %3$s (%4$d%%) from\n%1$s</string> + <string name="update_notification_title">Updating repositories</string> <string name="status_processing_xml_percent">Processing %2$s / %3$s (%4$d%%) from %1$s</string> <string name="status_connecting_to_repo">Connecting to\n%1$s</string> <string name="status_checking_compatibility">Checking apps compatibility with your device…</string> @@ -218,8 +219,6 @@ <string name="global_error_updating_repos">Error during update:</string> <string name="no_permissions">No permissions are used.</string> <string name="permissions_for_long">Permissions for version %s</string> - <string name="showPermissions">Show permissions</string> - <string name="showPermissions_on">Display a list of permissions an app requires</string> <string name="no_handler_app">You don\'t have any available app that can handle %s</string> <string name="compactlayout">Compact Layout</string> <string name="compactlayout_on">Show icons at a smaller size</string> @@ -368,10 +367,11 @@ <string name="swap_bluetooth_your_device">Your device is</string> <string name="swap_bluetooth_select_or_scan">Select from devices below, or press \"Scan\" from the menu to find more devices.</string> <string name="swap_bluetooth_bonded_device">Bonded</string> - <string name="swap_bluetooth_bonding_device">Currently bonding...</string> + <string name="swap_bluetooth_bonding_device">Currently bonding…</string> <string name="swap_bluetooth_unknown_device">Unknown device</string> - <string name="loading">Loading...</string> + <string name="loading">Loading…</string> <string name="swap_attempt_install">TRY TO INSTALL</string> + <string name="swap_connection_misc_error">An error occurred while connecting to device, we can\'t seem to swap with it :(</string> <string name="install_confirm">Do you want to install this application? It will get access to:</string> @@ -399,4 +399,13 @@ <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff33b5e5">NEW: </font></string> <string name="perms_description_app">Provided by %1$s.</string> + <string name="downloading">Downloading…</string> + + <string-array name="file_size_units"> + <item>B</item> + <item>KiB</item> + <item>MiB</item> + <item>GiB</item> + <item>TiB</item> + </string-array> </resources> diff --git a/F-Droid/res/values/styles.xml b/F-Droid/res/values/styles.xml index 15a1c5821..68b49c53c 100644 --- a/F-Droid/res/values/styles.xml +++ b/F-Droid/res/values/styles.xml @@ -6,6 +6,8 @@ <item name="colorPrimary">@color/fdroid_blue</item> <item name="colorPrimaryDark">@color/fdroid_blue_dark</item> <item name="colorAccent">@color/fdroid_green</item> + <item name="android:textColorLink">@color/fdroid_green</item> + <item name="alertDialogTheme">@style/AlertDialogThemeDark</item> </style> <style name="AppBaseThemeLight" parent="Theme.AppCompat.Light.DarkActionBar"> @@ -14,17 +16,14 @@ <item name="colorPrimary">@color/fdroid_blue</item> <item name="colorPrimaryDark">@color/fdroid_blue_dark</item> <item name="colorAccent">@color/fdroid_green</item> + <item name="android:textColorLink">@color/fdroid_green</item> + <item name="alertDialogTheme">@style/AlertDialogThemeLight</item> </style> <color name="black">#FF000000</color> <color name="white">#FFFFFFFF</color> <color name="red">#FFFF0000</color> - <style name="AboutDialogLight" parent="@android:style/Theme.Dialog"> - <item name="@android:windowBackground">@color/black</item> - <item name="@android:textColor">@color/white</item> - </style> - <style name="AppThemeDark" parent="AppBaseThemeDark"> <!-- customizations that are not API-level specific go here. --> </style> @@ -33,6 +32,16 @@ <!-- customizations that are not API-level specific go here. --> </style> + <style name="AlertDialogBaseThemeDark" parent="Theme.AppCompat.Dialog.Alert" /> + <style name="AlertDialogThemeDark" parent="AlertDialogBaseThemeDark"> + <item name="colorAccent">@color/fdroid_green</item> + </style> + + <style name="AlertDialogBaseThemeLight" parent="Theme.AppCompat.Light.Dialog.Alert" /> + <style name="AlertDialogThemeLight" parent="AlertDialogBaseThemeLight"> + <item name="colorAccent">@color/fdroid_green</item> + </style> + <style name="SwapTheme.Wizard" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorButtonNormal">@color/swap_bright_blue</item> <item name="android:actionBarStyle">@style/Widget.AppCompat.ActionBar.Solid</item> diff --git a/F-Droid/src/org/fdroid/fdroid/AppDetails.java b/F-Droid/src/org/fdroid/fdroid/AppDetails.java index f0a4d2fc4..6500551b0 100644 --- a/F-Droid/src/org/fdroid/fdroid/AppDetails.java +++ b/F-Droid/src/org/fdroid/fdroid/AppDetails.java @@ -21,28 +21,30 @@ package org.fdroid.fdroid; import android.app.Activity; -import android.app.AlertDialog; -import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.content.ActivityNotFoundException; +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.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.database.ContentObserver; import android.graphics.Bitmap; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.ListFragment; import android.support.v4.app.NavUtils; +import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; import android.text.Html; import android.text.Layout; import android.text.Selection; @@ -63,9 +65,11 @@ import android.view.Window; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @@ -90,6 +94,7 @@ import org.fdroid.fdroid.net.Downloader; import java.io.File; import java.security.NoSuchAlgorithmException; +import java.text.DecimalFormat; import java.util.Iterator; import java.util.List; @@ -113,7 +118,7 @@ interface AppInstallListener { void removeApk(String packageName); } -public class AppDetails extends ActionBarActivity implements ProgressListener, AppDetailsData, AppInstallListener { +public class AppDetails extends AppCompatActivity implements ProgressListener, AppDetailsData, AppInstallListener { private static final String TAG = "AppDetails"; @@ -124,7 +129,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A private FDroidApp fdroidApp; private ApkListAdapter adapter; - private ProgressDialog progressDialog; private static class ViewHolder { TextView version; @@ -316,6 +320,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A private App app; private PackageManager mPm; private ApkDownloader downloadHandler; + private LocalBroadcastManager localBroadcastManager; private boolean startingIgnoreAll; private int startingIgnoreThis; @@ -323,11 +328,14 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A private final Context mctx = this; private Installer installer; + + private AppDetailsHeaderFragment mHeaderFragment; + /** * Stores relevant data that we want to keep track of when destroying the activity * with the expectation of it being recreated straight away (e.g. after an * orientation change). One of the major things is that we want the download thread - * to stay active, but for it not to trigger any UI stuff (e.g. progress dialogs) + * to stay active, but for it not to trigger any UI stuff (e.g. progress bar) * between the activity being destroyed and recreated. */ private static class ConfigurationChangeHelper { @@ -418,13 +426,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A listFragment.removeSummaryHeader(); } - // Spinner seems to default to visible on Android 4.0.3 and 4.0.4 - // https://gitlab.com/fdroid/fdroidclient/issues/75 - // Can't put this in onResume(), because that is called on return from asking - // the user permission to use su (in which case we still want to show the - // progress indicator after returning from that prompt). - setSupportProgressBarIndeterminateVisibility(false); - + localBroadcastManager = LocalBroadcastManager.getInstance(this); } // The signature of the installed version. @@ -442,39 +444,35 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A myAppObserver); } - @Override - protected void onResume() { - super.onResume(); - if (downloadHandler != null) { - if (downloadHandler.isComplete()) { - downloadCompleteInstallApk(); - } else { - downloadHandler.setProgressListener(this); - - // Show the progress dialog, if for no other reason than to prevent them attempting - // to download again (i.e. we force them to touch 'cancel' before they can access - // the rest of the activity). - Log.d(TAG, "Showing dialog to user after resuming app details view, because a download was previously in progress"); - updateProgressDialog(); - } - } - } - @Override protected void onResumeFragments() { super.onResumeFragments(); refreshApkList(); refreshHeader(); supportInvalidateOptionsMenu(); + if (downloadHandler != null) { + if (downloadHandler.isComplete()) { + downloadCompleteInstallApk(); + } else { + localBroadcastManager.registerReceiver(downloaderProgressReceiver, + new IntentFilter(Downloader.LOCAL_ACTION_PROGRESS)); + downloadHandler.setProgressListener(this); + + if (downloadHandler.getTotalBytes() == 0) + mHeaderFragment.startProgress(); + else + mHeaderFragment.updateProgress(downloadHandler.getBytesRead(), downloadHandler.getTotalBytes()); + } + } } /** - * Remove progress listener, suppress progress dialog, set downloadHandler to null. + * Remove progress listener, suppress progress bar, set downloadHandler to null. */ private void cleanUpFinishedDownload() { if (downloadHandler != null) { downloadHandler.removeProgressListener(); - removeProgressDialog(); + mHeaderFragment.removeProgress(); downloadHandler = null; } } @@ -485,7 +483,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A */ private void downloadCompleteInstallApk() { if (downloadHandler != null) { - installApk(downloadHandler.localFile(), downloadHandler.getApk().id); + installApk(downloadHandler.localFile()); cleanUpFinishedDownload(); } } @@ -504,13 +502,23 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A setIgnoreUpdates(app.id, app.ignoreAllUpdates, app.ignoreThisUpdate); } + localBroadcastManager.unregisterReceiver(downloaderProgressReceiver); if (downloadHandler != null) { downloadHandler.removeProgressListener(); } - removeProgressDialog(); + mHeaderFragment.removeProgress(); } + private final BroadcastReceiver downloaderProgressReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mHeaderFragment != null) + mHeaderFragment.updateProgress(intent.getIntExtra(Downloader.EXTRA_BYTES_READ, -1), + intent.getIntExtra(Downloader.EXTRA_TOTAL_BYTES, -1)); + } + }; + private void onAppChanged() { if (!reset(app.id)) { AppDetails.this.finish(); @@ -553,13 +561,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A super.onDestroy(); } - private void removeProgressDialog() { - if (progressDialog != null) { - progressDialog.dismiss(); - progressDialog = null; - } - } - // Reset the display and list contents. Used when entering the activity, and // also when something has been installed/uninstalled. // Return true if the app was found, false otherwise. @@ -619,9 +620,9 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } private void refreshHeader() { - AppDetailsHeaderFragment headerFragment = (AppDetailsHeaderFragment) + mHeaderFragment = (AppDetailsHeaderFragment) getSupportFragmentManager().findFragmentById(R.id.header); - headerFragment.refresh(); + mHeaderFragment.updateViews(); } @Override @@ -725,8 +726,8 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } @Override - public boolean onTouchEvent(TextView widget, Spannable buffer, - MotionEvent event) { + public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer, + @NonNull MotionEvent event) { try { return super.onTouchEvent(widget, buffer, event); } catch (ActivityNotFoundException ex) { @@ -805,6 +806,10 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A // Install the version of this app denoted by 'app.curApk'. @Override public void install(final Apk apk) { + // Ignore call if another download is running. + if (downloadHandler != null && !downloadHandler.isComplete()) + return; + final String[] projection = { RepoProvider.DataColumns.ADDRESS }; Repo repo = RepoProvider.Helper.findById(this, apk.repo, projection); if (repo == null || repo.address == null) { @@ -854,32 +859,28 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A private void startDownload(Apk apk, String repoAddress) { downloadHandler = new ApkDownloader(getBaseContext(), apk, repoAddress); + localBroadcastManager.registerReceiver(downloaderProgressReceiver, + new IntentFilter(Downloader.LOCAL_ACTION_PROGRESS)); downloadHandler.setProgressListener(this); if (downloadHandler.download()) { - updateProgressDialog(); + mHeaderFragment.startProgress(); } } - private void installApk(File file, String packageName) { - setSupportProgressBarIndeterminateVisibility(true); - + private void installApk(File file) { try { installer.installPackage(file); } catch (AndroidNotCompatibleException e) { Log.e(TAG, "Android not compatible with this Installer!", e); - setSupportProgressBarIndeterminateVisibility(false); } } @Override public void removeApk(String packageName) { - setSupportProgressBarIndeterminateVisibility(true); - try { installer.deletePackage(packageName); } catch (AndroidNotCompatibleException e) { Log.e(TAG, "Android not compatible with this Installer!", e); - setSupportProgressBarIndeterminateVisibility(false); } } @@ -894,7 +895,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A PackageManagerCompat.setInstaller(mPm, app.id); } - setSupportProgressBarIndeterminateVisibility(false); onAppChanged(); } }); @@ -906,7 +906,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A runOnUiThread(new Runnable() { @Override public void run() { - setSupportProgressBarIndeterminateVisibility(false); onAppChanged(); } }); @@ -914,7 +913,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A runOnUiThread(new Runnable() { @Override public void run() { - setSupportProgressBarIndeterminateVisibility(false); onAppChanged(); Log.e(TAG, "Installer aborted with errorCode: " + errorCode); @@ -945,79 +943,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A startActivity(Intent.createChooser(shareIntent, getString(R.string.menu_share))); } - private ProgressDialog getProgressDialog(String file) { - if (progressDialog == null) { - final ProgressDialog pd = new ProgressDialog(this); - pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - if (Build.VERSION.SDK_INT >= 11) { - pd.setProgressNumberFormat("%1d/%2d KiB"); - } - pd.setMessage(getString(R.string.download_server) + ":\n " + file); - pd.setCancelable(true); - pd.setCanceledOnTouchOutside(false); - - // The indeterminate-ness will get overridden on the first progress event we receive. - pd.setIndeterminate(true); - - pd.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - Log.d(TAG, "User clicked 'cancel' on download, attempting to interrupt download thread."); - if (downloadHandler != null) { - downloadHandler.cancel(); - cleanUpFinishedDownload(); - } else { - Log.e(TAG, "Tried to cancel, but the downloadHandler doesn't exist."); - } - progressDialog = null; - Toast.makeText(AppDetails.this, getString(R.string.download_cancelled), Toast.LENGTH_LONG).show(); - } - }); - pd.setButton(DialogInterface.BUTTON_NEUTRAL, - getString(R.string.cancel), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - pd.cancel(); - } - } - ); - progressDialog = pd; - } - return progressDialog; - } - - /** - * Looks at the current <code>downloadHandler</code> and finds it's size and progress. - * This is in comparison to {@link org.fdroid.fdroid.AppDetails#updateProgressDialog(int, int)}, - * which is used when you have the details from a freshly received - * {@link org.fdroid.fdroid.ProgressListener.Event}. - */ - private void updateProgressDialog() { - if (downloadHandler != null) { - updateProgressDialog(downloadHandler.getProgress(), downloadHandler.getTotalSize()); - } - } - - private void updateProgressDialog(int progress, int total) { - if (downloadHandler != null) { - ProgressDialog pd = getProgressDialog(downloadHandler.getRemoteAddress()); - if (total > 0) { - pd.setIndeterminate(false); - pd.setProgress(progress/1024); - pd.setMax(total/1024); - } else { - pd.setIndeterminate(true); - pd.setProgress(progress/1024); - pd.setMax(0); - } - if (!pd.isShowing()) { - Log.d(TAG, "Showing progress dialog for download."); - pd.show(); - } - } - } - @Override public void onProgress(Event event) { if (downloadHandler == null || !downloadHandler.isEventFromThis(event)) { @@ -1034,9 +959,6 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A boolean finished = false; switch (event.type) { - case Downloader.EVENT_PROGRESS: - updateProgressDialog(event.progress, event.total); - break; case ApkDownloader.EVENT_ERROR: final String text; if (event.getData().getInt(ApkDownloader.EVENT_DATA_ERROR_TYPE) == ApkDownloader.ERROR_HASH_MISMATCH) @@ -1054,7 +976,8 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } if (finished) { - removeProgressDialog(); + if (mHeaderFragment != null) + mHeaderFragment.removeProgress(); downloadHandler = null; } } @@ -1447,9 +1370,14 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } } - public static class AppDetailsHeaderFragment extends Fragment { + public static class AppDetailsHeaderFragment extends Fragment implements View.OnClickListener { private AppDetailsData data; + private Button btMain; + private ProgressBar progressBar; + private TextView progressSize; + private TextView progressPercent; + private ImageButton cancelButton; protected final DisplayImageOptions displayImageOptions; public static boolean installed = false; public static boolean updateWanted = false; @@ -1493,35 +1421,120 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A TextView tv = (TextView) view.findViewById(R.id.title); tv.setText(getApp().name); + btMain = (Button) view.findViewById(R.id.btn_main); + progressBar = (ProgressBar) view.findViewById(R.id.progress_bar); + progressSize = (TextView) view.findViewById(R.id.progress_size); + progressPercent = (TextView) view.findViewById(R.id.progress_percentage); + cancelButton = (ImageButton) view.findViewById(R.id.cancel); + progressBar.setIndeterminate(false); + cancelButton.setOnClickListener(this); + updateViews(view); } @Override public void onResume() { super.onResume(); - refresh(); + updateViews(); } - public void refresh() { + /** + * Displays empty, indeterminate progress bar and related views. + */ + public void startProgress() { + setProgressVisible(true); + progressBar.setIndeterminate(true); + progressSize.setText(""); + progressPercent.setText(""); + updateViews(); + } + + /** + * Updates progress bar and captions to new values (in bytes). + */ + public void updateProgress(long progress, long total) { + long percent = progress * 100 / total; + setProgressVisible(true); + progressBar.setIndeterminate(false); + progressBar.setProgress((int) percent); + progressBar.setMax(100); + progressSize.setText(readableFileSize(progress) + " / " + readableFileSize(total)); + progressPercent.setText(Long.toString(percent) + " %"); + } + + /** + * Converts a number of bytes to a human readable file size (eg 3.5 GiB). + * + * Based on http://stackoverflow.com/a/5599842 + */ + public String readableFileSize(long bytes) { + final String[] units = getResources().getStringArray(R.array.file_size_units); + if (bytes <= 0) return "0 " + units[0]; + int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024)); + return new DecimalFormat("#,##0.#") + .format(bytes / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; + } + + /** + * Shows or hides progress bar and related views. + */ + private void setProgressVisible(boolean visible) { + int state = (visible) ? View.VISIBLE : View.GONE; + progressBar.setVisibility(state); + progressSize.setVisibility(state); + progressPercent.setVisibility(state); + cancelButton.setVisibility(state); + } + + /** + * Removes progress bar and related views, invokes {@link #updateViews()}. + */ + public void removeProgress() { + setProgressVisible(false); + updateViews(); + } + + /** + * Cancels download and hides progress bar. + */ + @Override + public void onClick(View view) { + AppDetails activity = (AppDetails) getActivity(); + if (activity == null || activity.downloadHandler == null) + return; + + activity.downloadHandler.cancel(); + activity.cleanUpFinishedDownload(); + setProgressVisible(false); + updateViews(); + } + + public void updateViews() { updateViews(getView()); } public void updateViews(View view) { TextView statusView = (TextView) view.findViewById(R.id.status); - Button btMain = (Button) view.findViewById(R.id.btn_main); btMain.setVisibility(View.VISIBLE); + AppDetails activity = (AppDetails) getActivity(); + if (activity.downloadHandler != null) { + btMain.setText(R.string.downloading); + btMain.setEnabled(false); + } /* Check count > 0 due to incompatible apps resulting in an empty list. If App isn't installed */ - if (!getApp().isInstalled() && getApp().suggestedVercode > 0 && ((AppDetails)getActivity()).adapter.getCount() > 0) { + else if (!getApp().isInstalled() && getApp().suggestedVercode > 0 && + ((AppDetails)getActivity()).adapter.getCount() > 0) { installed = false; statusView.setText(getString(R.string.details_notinstalled)); NfcHelper.disableAndroidBeam(getActivity()); // Set Install button and hide second button btMain.setText(R.string.menu_install); btMain.setOnClickListener(mOnClickListener); + btMain.setEnabled(true); } // If App is installed else if (getApp().isInstalled()) { @@ -1541,6 +1554,7 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A } } btMain.setOnClickListener(mOnClickListener); + btMain.setEnabled(true); } TextView currentVersion = (TextView) view.findViewById(R.id.current_version); if (!getApks().isEmpty()) { @@ -1574,6 +1588,8 @@ public class AppDetails extends ActionBarActivity implements ProgressListener, A // If not installed, install else if (getApp().suggestedVercode > 0) { + btMain.setEnabled(false); + btMain.setText(R.string.system_install_installing); final Apk apkToInstall = ApkProvider.Helper.find(getActivity(), getApp().id, getApp().suggestedVercode); ((AppDetails)getActivity()).install(apkToInstall); } diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index 4fce5be34..768deb6b5 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -19,7 +19,6 @@ package org.fdroid.fdroid; -import android.app.AlertDialog; import android.app.NotificationManager; import android.app.SearchManager; import android.bluetooth.BluetoothAdapter; @@ -30,13 +29,12 @@ import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -56,7 +54,6 @@ public class FDroid extends ActionBarActivity { private static final String TAG = "FDroid"; - public static final int REQUEST_MANAGEREPOS = 0; public static final int REQUEST_PREFS = 1; public static final int REQUEST_ENABLE_BLUETOOTH = 2; public static final int REQUEST_SWAP = 3; @@ -246,12 +243,11 @@ public class FDroid extends ActionBarActivity { switch (item.getItemId()) { case R.id.action_update_repo: - updateRepos(); + UpdateService.updateNow(this); return true; case R.id.action_manage_repos: - Intent i = new Intent(this, ManageReposActivity.class); - startActivityForResult(i, REQUEST_MANAGEREPOS); + startActivity(new Intent(this, ManageReposActivity.class)); return true; case R.id.action_settings: @@ -279,16 +275,7 @@ public class FDroid extends ActionBarActivity { return true; case R.id.action_about: - View view; - if (Build.VERSION.SDK_INT >= 11) { - LayoutInflater li = LayoutInflater.from(this); - view = li.inflate(R.layout.about, null); - } else { - view = View.inflate( - new ContextThemeWrapper(this, R.style.AboutDialogLight), - R.layout.about, null); - } - + View view = LayoutInflater.from(this).inflate(R.layout.about, null); // Fill in the version... try { PackageInfo pi = getPackageManager() @@ -299,17 +286,8 @@ public class FDroid extends ActionBarActivity { } catch (Exception ignored) { } - AlertDialog.Builder builder; - if (Build.VERSION.SDK_INT >= 11) { - builder = new AlertDialog.Builder(this).setView(view); - } else { - builder = new AlertDialog.Builder( - new ContextThemeWrapper( - this, R.style.AboutDialogLight) - ).setView(view); - } + AlertDialog.Builder builder = new AlertDialog.Builder(this).setView(view); final AlertDialog alrt = builder.create(); - alrt.setIcon(R.drawable.ic_launcher); alrt.setTitle(getString(R.string.about_title)); alrt.setButton(AlertDialog.BUTTON_NEUTRAL, getString(R.string.about_website), @@ -338,32 +316,6 @@ public class FDroid extends ActionBarActivity { protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case REQUEST_MANAGEREPOS: - if (data != null && data.hasExtra(ManageReposActivity.REQUEST_UPDATE)) { - AlertDialog.Builder ask_alrt = new AlertDialog.Builder(this); - ask_alrt.setTitle(getString(R.string.repo_update_title)); - ask_alrt.setIcon(android.R.drawable.ic_menu_rotate); - ask_alrt.setMessage(getString(R.string.repo_alrt)); - ask_alrt.setPositiveButton(getString(R.string.yes), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int whichButton) { - updateRepos(); - } - }); - ask_alrt.setNegativeButton(getString(R.string.no), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int whichButton) { - // do nothing - } - }); - AlertDialog alert = ask_alrt.create(); - alert.show(); - } - break; case REQUEST_PREFS: // The automatic update settings may have changed, so reschedule (or // unschedule) the service accordingly. It's cheap, so no need to @@ -398,13 +350,6 @@ public class FDroid extends ActionBarActivity { }); } - // Force a repo update now. A progress dialog is shown and the UpdateService - // is told to do the update, which will result in the database changing. The - // UpdateReceiver class should get told when this is finished. - public void updateRepos() { - UpdateService.updateNow(this); - } - private TabManager getTabManager() { if (tabManager == null) { tabManager = new TabManager(this, viewPager); diff --git a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java index ab1df5825..85cdbe56d 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroidApp.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroidApp.java @@ -74,7 +74,8 @@ public class FDroidApp extends Application { } public enum Theme { - dark, light, lightWithDarkActionBar + dark, + light, } private static Theme curTheme = Theme.light; @@ -100,7 +101,7 @@ public class FDroidApp extends Application { case light: return R.style.AppThemeLight; default: - return R.style.AppThemeDark; + return R.style.AppThemeLight; } } diff --git a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java index f3cff0b8b..936d2e963 100644 --- a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java @@ -3,7 +3,6 @@ package org.fdroid.fdroid; import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageManager; -import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; @@ -22,6 +21,8 @@ import org.xml.sax.XMLReader; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -52,16 +53,14 @@ public class RepoUpdater { /** * Updates an app repo as read out of the database into a {@link Repo} instance. - * - * @param context - * @param repo a {@link Repo} read out of the local database + * @param repo A {@link Repo} read out of the local database */ public RepoUpdater(@NonNull Context context, @NonNull Repo repo) { this.context = context; this.repo = repo; } - public void setProgressListener(ProgressListener progressListener) { + public void setProgressListener(@Nullable ProgressListener progressListener) { this.progressListener = progressListener; } @@ -71,29 +70,23 @@ public class RepoUpdater { public List<Apk> getApks() { return apks; } - protected String getIndexAddress() { + protected URL getIndexAddress() throws MalformedURLException { + String urlString = repo.address + "/index.jar"; try { String versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; - return repo.address + "/index.jar?client_version=" + versionName; + urlString += "?client_version=" + versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } - return repo.address + "/index.jar"; + return new URL(urlString); } Downloader downloadIndex() throws UpdateException { Downloader downloader = null; try { - downloader = DownloaderFactory.create( + downloader = DownloaderFactory.create(context, getIndexAddress(), File.createTempFile("index-", "-downloaded", context.getCacheDir())); downloader.setCacheTag(repo.lastetag); - - if (progressListener != null) { // interactive session, show progress - Bundle data = new Bundle(1); - data.putString(PROGRESS_DATA_REPO_ADDRESS, repo.address); - downloader.setProgressListener(progressListener, data); - } - downloader.downloadUninterrupted(); if (downloader.isCached()) { diff --git a/F-Droid/src/org/fdroid/fdroid/UpdateService.java b/F-Droid/src/org/fdroid/fdroid/UpdateService.java index 0c6f83201..3e75ff7db 100644 --- a/F-Droid/src/org/fdroid/fdroid/UpdateService.java +++ b/F-Droid/src/org/fdroid/fdroid/UpdateService.java @@ -22,11 +22,12 @@ import android.app.AlarmManager; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; -import android.app.ProgressDialog; +import android.content.BroadcastReceiver; import android.content.ContentProviderOperation; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.OperationApplicationException; import android.content.SharedPreferences; import android.database.Cursor; @@ -34,15 +35,12 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; -import android.os.Bundle; -import android.os.Handler; import android.os.RemoteException; -import android.os.ResultReceiver; import android.os.SystemClock; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; +import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -64,30 +62,28 @@ public class UpdateService extends IntentService implements ProgressListener { private static final String TAG = "UpdateService"; - public static final String RESULT_MESSAGE = "msg"; - public static final String RESULT_EVENT = "event"; - public static final String RESULT_REPO_ERRORS = "repoErrors"; + public static final String LOCAL_ACTION_STATUS = "status"; + + public static final String EXTRA_MESSAGE = "msg"; + public static final String EXTRA_REPO_ERRORS = "repoErrors"; + public static final String EXTRA_STATUS_CODE = "status"; + public static final String EXTRA_ADDRESS = "address"; + public static final String EXTRA_MANUAL_UPDATE = "manualUpdate"; public static final int STATUS_COMPLETE_WITH_CHANGES = 0; - public static final int STATUS_COMPLETE_AND_SAME = 1; - public static final int STATUS_ERROR_GLOBAL = 2; - public static final int STATUS_ERROR_LOCAL = 3; - public static final int STATUS_ERROR_LOCAL_SMALL = 4; - public static final int STATUS_INFO = 5; + public static final int STATUS_COMPLETE_AND_SAME = 1; + public static final int STATUS_ERROR_GLOBAL = 2; + public static final int STATUS_ERROR_LOCAL = 3; + public static final int STATUS_ERROR_LOCAL_SMALL = 4; + public static final int STATUS_INFO = 5; - // I don't like that I've had to dupliacte the statuses above with strings here, however - // one method of communication/notification is using ResultReceiver (int status codes) - // while the other uses progress events (string event types). - public static final String EVENT_COMPLETE_WITH_CHANGES = "repoUpdateComplete (changed)"; - public static final String EVENT_COMPLETE_AND_SAME = "repoUpdateComplete (not changed)"; - public static final String EVENT_FINISHED = "repoUpdateFinished"; - public static final String EVENT_ERROR = "repoUpdateError"; - public static final String EVENT_INFO = "repoUpdateInfo"; + private LocalBroadcastManager localBroadcastManager; - public static final String EXTRA_RECEIVER = "receiver"; - public static final String EXTRA_ADDRESS = "address"; + private static final int NOTIFY_ID_UPDATING = 0; + private static final int NOTIFY_ID_UPDATES_AVAILABLE = 1; - private ResultReceiver receiver = null; + private NotificationManager notificationManager; + private NotificationCompat.Builder notificationBuilder; public UpdateService() { super("UpdateService"); @@ -107,138 +103,17 @@ public class UpdateService extends IntentService implements ProgressListener { AppProvider.DataColumns.IGNORE_THISUPDATE }; - // For receiving results from the UpdateService when we've told it to - // update in response to a user request. - public static class UpdateReceiver extends ResultReceiver { - - private final Context context; - private ProgressDialog dialog; - private ProgressListener listener; - private String lastShownMessage = null; - - public UpdateReceiver(@NonNull Context context, Handler handler) { - super(handler); - this.context = context; - } - - public UpdateReceiver setDialog(ProgressDialog dialog) { - this.dialog = dialog; - return this; - } - - public UpdateReceiver setListener(ProgressListener listener) { - this.listener = listener; - return this; - } - - private void forwardEvent(String type) { - if (listener != null) { - listener.onProgress(new Event(type)); - } - } - - private void ensureDialog() { - if (dialog == null) { - String title = context.getString(R.string.process_wait_title); - String message = lastShownMessage == null ? context.getString(R.string.process_update_msg) : lastShownMessage; - dialog = ProgressDialog.show(context, title, message, true, true); - dialog.setIcon(android.R.drawable.ic_dialog_info); - dialog.setCanceledOnTouchOutside(false); - } - } - - public UpdateReceiver showDialog() { - ensureDialog(); - dialog.show(); - return this; - } - - public void hideDialog() { - if (dialog != null) { - dialog.hide(); - dialog.dismiss(); - dialog = null; - } - } - - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - final String message = resultData.getString(RESULT_MESSAGE); - boolean finished = false; - switch (resultCode) { - case STATUS_ERROR_GLOBAL: - forwardEvent(EVENT_ERROR); - Toast.makeText(context, context.getString(R.string.global_error_updating_repos) + " " + message, Toast.LENGTH_LONG).show(); - finished = true; - break; - case STATUS_ERROR_LOCAL: - case STATUS_ERROR_LOCAL_SMALL: - StringBuilder msgB = new StringBuilder(); - List<CharSequence> repoErrors = resultData.getCharSequenceArrayList(RESULT_REPO_ERRORS); - for (CharSequence error : repoErrors) { - if (msgB.length() > 0) msgB.append('\n'); - msgB.append(error); - } - if (resultCode == STATUS_ERROR_LOCAL_SMALL) { - msgB.append('\n').append(context.getString(R.string.all_other_repos_fine)); - } - Toast.makeText(context, msgB.toString(), Toast.LENGTH_LONG).show(); - finished = true; - break; - case STATUS_COMPLETE_WITH_CHANGES: - forwardEvent(EVENT_COMPLETE_WITH_CHANGES); - finished = true; - break; - case STATUS_COMPLETE_AND_SAME: - forwardEvent(EVENT_COMPLETE_AND_SAME); - Toast.makeText(context, context.getString(R.string.repos_unchanged), Toast.LENGTH_LONG).show(); - finished = true; - break; - case STATUS_INFO: - forwardEvent(EVENT_INFO); - if (dialog != null) { - lastShownMessage = message; - dialog.setMessage(message); - } - break; - } - - if (finished) { - forwardEvent(EVENT_FINISHED); - if (dialog != null && dialog.isShowing()) { - try { - dialog.dismiss(); - } catch (IllegalArgumentException e) { - // sometimes dialog.isShowing() doesn't work :( - // https://stackoverflow.com/questions/19538282/view-not-attached-to-window-manager-dialog-dismiss - e.printStackTrace(); - } - } - } - } + public static void updateNow(Context context) { + updateRepoNow(null, context); } - public static UpdateReceiver updateNow(Context context) { - return updateRepoNow(null, context); - } - - public static UpdateReceiver updateRepoNow(String address, Context context) { - return updateRepoNow(address, context, true); - } - - public static UpdateReceiver updateRepoNow(String address, Context context, boolean showDialog) { + public static void updateRepoNow(String address, Context context) { Intent intent = new Intent(context, UpdateService.class); - UpdateReceiver receiver = new UpdateReceiver(context, new Handler()); - if (showDialog) { - receiver.showDialog(); - } - intent.putExtra(EXTRA_RECEIVER, receiver); + intent.putExtra(EXTRA_MANUAL_UPDATE, true); if (!TextUtils.isEmpty(address)) { intent.putExtra(EXTRA_ADDRESS, address); } context.startService(intent); - - return receiver; } // Schedule (or cancel schedule for) this service, according to the @@ -268,36 +143,135 @@ public class UpdateService extends IntentService implements ProgressListener { } + @Override + public void onCreate() { + super.onCreate(); + + localBroadcastManager = LocalBroadcastManager.getInstance(this); + localBroadcastManager.registerReceiver(downloadProgressReceiver, + new IntentFilter(Downloader.LOCAL_ACTION_PROGRESS)); + localBroadcastManager.registerReceiver(updateStatusReceiver, + new IntentFilter(LOCAL_ACTION_STATUS)); + + notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + notificationBuilder = new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.ic_refresh_white) + .setOngoing(true) + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setContentTitle(getString(R.string.update_notification_title)); + notificationManager.notify(NOTIFY_ID_UPDATING, notificationBuilder.build()); + } + + @Override + public void onDestroy() { + super.onDestroy(); + notificationManager.cancel(NOTIFY_ID_UPDATING); + localBroadcastManager.unregisterReceiver(downloadProgressReceiver); + localBroadcastManager.unregisterReceiver(updateStatusReceiver); + } + protected void sendStatus(int statusCode) { sendStatus(statusCode, null); } protected void sendStatus(int statusCode, String message) { - if (receiver != null) { - Bundle resultData = new Bundle(); - if (!TextUtils.isEmpty(message)) { - resultData.putString(RESULT_MESSAGE, message); - } - receiver.send(statusCode, resultData); - } + Intent intent = new Intent(LOCAL_ACTION_STATUS); + intent.putExtra(EXTRA_STATUS_CODE, statusCode); + if (!TextUtils.isEmpty(message)) + intent.putExtra(EXTRA_MESSAGE, message); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } protected void sendRepoErrorStatus(int statusCode, ArrayList<CharSequence> repoErrors) { - if (receiver != null) { - Bundle resultData = new Bundle(); - resultData.putCharSequenceArrayList(RESULT_REPO_ERRORS, repoErrors); - receiver.send(statusCode, resultData); - } + Intent intent = new Intent(LOCAL_ACTION_STATUS); + intent.putExtra(EXTRA_STATUS_CODE, statusCode); + intent.putExtra(EXTRA_REPO_ERRORS, repoErrors.toArray(new CharSequence[repoErrors.size()])); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } - /** - * We might be doing a scheduled run, or we might have been launched by the - * app in response to a user's request. If we have a receiver, it's the - * latter... - */ - private boolean isScheduledRun() { - return receiver == null; - } + private final BroadcastReceiver downloadProgressReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (TextUtils.isEmpty(action)) + return; + + if (!action.equals(Downloader.LOCAL_ACTION_PROGRESS)) + return; + + String repoAddress = intent.getStringExtra(Downloader.EXTRA_ADDRESS); + int downloadedSize = intent.getIntExtra(Downloader.EXTRA_BYTES_READ, -1); + int totalSize = intent.getIntExtra(Downloader.EXTRA_TOTAL_BYTES, -1); + int percent = (int) ((double) downloadedSize / totalSize * 100); + sendStatus(STATUS_INFO, + getString(R.string.status_download, repoAddress, + Utils.getFriendlySize(downloadedSize), + Utils.getFriendlySize(totalSize), percent)); + } + }; + + // For receiving results from the UpdateService when we've told it to + // update in response to a user request. + private final BroadcastReceiver updateStatusReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (TextUtils.isEmpty(action)) + return; + + if (!action.equals(LOCAL_ACTION_STATUS)) + return; + + final String message = intent.getStringExtra(EXTRA_MESSAGE); + int resultCode = intent.getIntExtra(EXTRA_STATUS_CODE, -1); + + String text; + switch (resultCode) { + case STATUS_INFO: + notificationBuilder.setContentText(message) + .setProgress(0, 0, true) + .setCategory(NotificationCompat.CATEGORY_SERVICE); + notificationManager.notify(NOTIFY_ID_UPDATING, notificationBuilder.build()); + break; + case STATUS_ERROR_GLOBAL: + text = context.getString(R.string.global_error_updating_repos) + " " + message; + notificationBuilder.setContentText(text) + .setCategory(NotificationCompat.CATEGORY_ERROR) + .setSmallIcon(android.R.drawable.ic_dialog_alert); + notificationManager.notify(NOTIFY_ID_UPDATING, notificationBuilder.build()); + Toast.makeText(context, text, Toast.LENGTH_LONG).show(); + break; + case STATUS_ERROR_LOCAL: + case STATUS_ERROR_LOCAL_SMALL: + StringBuilder msgBuilder = new StringBuilder(); + CharSequence[] repoErrors = intent.getCharSequenceArrayExtra(EXTRA_REPO_ERRORS); + for (CharSequence error : repoErrors) { + if (msgBuilder.length() > 0) msgBuilder.append('\n'); + msgBuilder.append(error); + } + if (resultCode == STATUS_ERROR_LOCAL_SMALL) { + msgBuilder.append('\n').append(context.getString(R.string.all_other_repos_fine)); + } + text = msgBuilder.toString(); + notificationBuilder.setContentText(text) + .setCategory(NotificationCompat.CATEGORY_ERROR) + .setSmallIcon(android.R.drawable.ic_dialog_info); + notificationManager.notify(NOTIFY_ID_UPDATING, notificationBuilder.build()); + Toast.makeText(context, text, Toast.LENGTH_LONG).show(); + break; + case STATUS_COMPLETE_WITH_CHANGES: + break; + case STATUS_COMPLETE_AND_SAME: + text = context.getString(R.string.repos_unchanged); + notificationBuilder.setContentText(text) + .setCategory(NotificationCompat.CATEGORY_SERVICE); + notificationManager.notify(NOTIFY_ID_UPDATING, notificationBuilder.build()); + break; + } + } + }; /** * Check whether it is time to run the scheduled update. @@ -341,15 +315,14 @@ public class UpdateService extends IntentService implements ProgressListener { @Override protected void onHandleIntent(Intent intent) { - receiver = intent.getParcelableExtra(EXTRA_RECEIVER); String address = intent.getStringExtra(EXTRA_ADDRESS); + boolean manualUpdate = intent.getBooleanExtra(EXTRA_MANUAL_UPDATE, false); - long startTime = System.currentTimeMillis(); try { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); // See if it's time to actually do anything yet... - if (!isScheduledRun()) { + if (manualUpdate) { Log.d(TAG, "Unscheduled (manually requested) update"); } else if (!verifyIsTimeForScheduledRun()) { return; @@ -469,11 +442,6 @@ public class UpdateService extends IntentService implements ProgressListener { "Exception during update processing:\n" + Log.getStackTraceString(e)); sendStatus(STATUS_ERROR_GLOBAL, e.getMessage()); - } finally { - Log.d(TAG, "Update took " - + ((System.currentTimeMillis() - startTime) / 1000) - + " seconds."); - receiver = null; } } @@ -566,8 +534,7 @@ public class UpdateService extends IntentService implements ProgressListener { .setContentText(contentText) .setStyle(createNotificationBigStyle(hasUpdates)); - NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.notify(1, builder.build()); + notificationManager.notify(NOTIFY_ID_UPDATES_AVAILABLE, builder.build()); } private List<String> getKnownAppIds(List<App> apps) { @@ -792,9 +759,6 @@ public class UpdateService extends IntentService implements ProgressListener { String totalSize = Utils.getFriendlySize(event.total); int percent = (int) ((double) event.progress / event.total * 100); switch (event.type) { - case Downloader.EVENT_PROGRESS: - message = getString(R.string.status_download, repoAddress, downloadedSize, totalSize, percent); - break; case RepoUpdater.PROGRESS_TYPE_PROCESS_XML: message = getString(R.string.status_processing_xml_percent, repoAddress, downloadedSize, totalSize, percent); break; diff --git a/F-Droid/src/org/fdroid/fdroid/Utils.java b/F-Droid/src/org/fdroid/fdroid/Utils.java index 9bfc4909c..a555f3a04 100644 --- a/F-Droid/src/org/fdroid/fdroid/Utils.java +++ b/F-Droid/src/org/fdroid/fdroid/Utils.java @@ -436,7 +436,8 @@ public final class Utils { return new CommaSeparatedList(sb.toString()); } - public static CommaSeparatedList make(String list) { + @Nullable + public static CommaSeparatedList make(@Nullable String list) { if (TextUtils.isEmpty(list)) return null; return new CommaSeparatedList(list); diff --git a/F-Droid/src/org/fdroid/fdroid/data/App.java b/F-Droid/src/org/fdroid/fdroid/data/App.java index 985dd749f..2ed33f98b 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/App.java +++ b/F-Droid/src/org/fdroid/fdroid/data/App.java @@ -114,7 +114,8 @@ public class App extends ValueObject implements Comparable<App> { checkCursorPosition(cursor); for (int i = 0; i < cursor.getColumnCount(); i++) { - switch (cursor.getColumnName(i)) { + String n = cursor.getColumnName(i); + switch (n) { case AppProvider.DataColumns.IS_COMPATIBLE: compatible = cursor.getInt(i) == 1; break; @@ -208,6 +209,10 @@ public class App extends ValueObject implements Comparable<App> { case AppProvider.DataColumns.InstalledApp.VERSION_NAME: installedVersionName = cursor.getString(i); break; + case "_id": + break; + default: + Log.e(TAG, "Unknown column name " + n); } } } diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index e40922072..e9c742969 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -5,6 +5,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; @@ -98,8 +99,9 @@ public class AppProvider extends FDroidProvider { cursor.moveToFirst(); while (!cursor.isAfterLast()) { final String categoriesString = cursor.getString(0); - if (categoriesString != null) { - for (final String s : Utils.CommaSeparatedList.make(categoriesString)) { + Utils.CommaSeparatedList categoriesList = Utils.CommaSeparatedList.make(categoriesString); + if (categoriesList != null) { + for (final String s : categoriesList) { categorySet.add(s); } } @@ -152,6 +154,22 @@ public class AppProvider extends FDroidProvider { } + /** + * Class that only exists to call private methods in the {@link AppProvider} without having + * to go via a Context/ContentResolver. The reason is that if the {@link DBHelper} class + * was to try and use its getContext().getContentResolver() in order to access the app + * provider, then the AppProvider will end up creating a new instance of a writeable + * SQLiteDatabase. This causes problems because the {@link DBHelper} still has its reference + * open and locks certain tables. + */ + static final class UpgradeHelper { + + public static void updateIconUrls(Context context, SQLiteDatabase db) { + AppProvider.updateIconUrls(context, db); + } + + } + public interface DataColumns { String _ID = "rowid as _id"; // Required for CursorLoaders @@ -806,7 +824,7 @@ public class AppProvider extends FDroidProvider { updateCompatibleFlags(); updateSuggestedFromLatest(); updateSuggestedFromUpstream(); - updateIconUrls(); + updateIconUrls(getContext(), write()); } /** @@ -939,11 +957,13 @@ public class AppProvider extends FDroidProvider { } /** - * Updates URLs to icons + * Made static so that the {@link org.fdroid.fdroid.data.AppProvider.UpgradeHelper} can access + * it without instantiating an {@link AppProvider}. This is also the reason it needs to accept + * the context and database as arguments. */ - public void updateIconUrls() { - final String iconsDir = Utils.getIconsDir(getContext(), 1.0); - final String iconsDirLarge = Utils.getIconsDir(getContext(), 1.5); + private static void updateIconUrls(Context context, SQLiteDatabase db) { + final String iconsDir = Utils.getIconsDir(context, 1.0); + final String iconsDirLarge = Utils.getIconsDir(context, 1.5); String repoVersion = Integer.toString(Repo.VERSION_DENSITY_SPECIFIC_ICONS); Log.d(TAG, "Updating icon paths for apps belonging to repos with version >= " + repoVersion); @@ -953,7 +973,7 @@ public class AppProvider extends FDroidProvider { final String[] params = { repoVersion, iconsDir, Utils.FALLBACK_ICONS_DIR, repoVersion, iconsDirLarge, Utils.FALLBACK_ICONS_DIR }; - write().execSQL(query, params); + db.execSQL(query, params); } /** @@ -961,7 +981,7 @@ public class AppProvider extends FDroidProvider { * 1) The repo version that introduced density specific icons * 2) The dir to density specific icons for the current device. */ - private String getIconUpdateQuery() { + private static String getIconUpdateQuery() { final String apk = DBHelper.TABLE_APK; final String app = DBHelper.TABLE_APP; diff --git a/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java b/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java index 86b8f363f..ea3a153b0 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java +++ b/F-Droid/src/org/fdroid/fdroid/data/DBHelper.java @@ -101,7 +101,7 @@ public class DBHelper extends SQLiteOpenHelper { + InstalledAppProvider.DataColumns.APPLICATION_LABEL + " TEXT NOT NULL " + " );"; - private static final int DB_VERSION = 49; + private static final int DB_VERSION = 50; private final Context context; @@ -284,6 +284,7 @@ public class DBHelper extends SQLiteOpenHelper { addIsSwapToRepo(db, oldVersion); addChangelogToApp(db, oldVersion); addIconUrlLargeToApp(db, oldVersion); + updateIconUrlLarge(db, oldVersion); } /** @@ -432,6 +433,24 @@ public class DBHelper extends SQLiteOpenHelper { } } + private void updateIconUrlLarge(SQLiteDatabase db, int oldVersion) { + if (oldVersion < 50) { + Log.i(TAG, "Recalculating app icon URLs so that the newly added large icons will get updated."); + AppProvider.UpgradeHelper.updateIconUrls(context, db); + clearRepoEtags(db); + } + } + + /** + * By clearing the etags stored in the repo table, it means that next time the user updates + * their repos (either manually or on a scheduled task), they will update regardless of whether + * they have changed since last update or not. + */ + private void clearRepoEtags(SQLiteDatabase db) { + Log.i(TAG, "Clearing repo etags, so next update will not be skipped with \"Repos up to date\"."); + db.execSQL("update " + TABLE_REPO + " set lastetag = NULL"); + } + private void resetTransient(SQLiteDatabase db, int oldVersion) { // Before version 42, only transient info was stored in here. As of some time // just before 42 (F-Droid 0.60ish) it now has "ignore this version" info which @@ -443,7 +462,7 @@ public class DBHelper extends SQLiteOpenHelper { .putBoolean("triedEmptyUpdate", false).commit(); db.execSQL("drop table " + TABLE_APP); db.execSQL("drop table " + TABLE_APK); - db.execSQL("update " + TABLE_REPO + " set lastetag = NULL"); + clearRepoEtags(db); createAppApk(db); } } diff --git a/F-Droid/src/org/fdroid/fdroid/installer/AppSecurityPermissions.java b/F-Droid/src/org/fdroid/fdroid/installer/AppSecurityPermissions.java index 3c2c0c5aa..f3c18ab5b 100644 --- a/F-Droid/src/org/fdroid/fdroid/installer/AppSecurityPermissions.java +++ b/F-Droid/src/org/fdroid/fdroid/installer/AppSecurityPermissions.java @@ -18,7 +18,6 @@ package org.fdroid.fdroid.installer; import android.annotation.TargetApi; -import android.app.AlertDialog; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -29,6 +28,7 @@ import android.content.pm.PermissionInfo; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Parcel; +import android.support.v7.app.AlertDialog; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.util.AttributeSet; diff --git a/F-Droid/src/org/fdroid/fdroid/installer/InstallIntoSystemDialogActivity.java b/F-Droid/src/org/fdroid/fdroid/installer/InstallIntoSystemDialogActivity.java index cb4717b2b..ded1cabb3 100644 --- a/F-Droid/src/org/fdroid/fdroid/installer/InstallIntoSystemDialogActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/installer/InstallIntoSystemDialogActivity.java @@ -20,7 +20,6 @@ package org.fdroid.fdroid.installer; import android.app.Activity; -import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -32,6 +31,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NotificationCompat; +import android.support.v7.app.AlertDialog; import android.text.Html; import android.util.Log; import android.view.ContextThemeWrapper; diff --git a/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java b/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java index 8794409ec..0a1cd08e2 100644 --- a/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java +++ b/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java @@ -21,7 +21,6 @@ package org.fdroid.fdroid.installer; import android.app.Activity; -import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -30,6 +29,7 @@ import android.content.pm.IPackageInstallObserver; import android.content.pm.PackageManager; import android.net.Uri; import android.os.RemoteException; +import android.support.v7.app.AlertDialog; import android.util.Log; import org.fdroid.fdroid.R; diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java index aac4008dc..ea917a218 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java @@ -152,13 +152,13 @@ public class SwapService extends Service { return appsToSwap; } - @Nullable - public UpdateService.UpdateReceiver refreshSwap() { - return this.peer != null ? connectTo(peer, false) : null; + public void refreshSwap() { + if (peer != null) { + connectTo(peer, false); + } } - @NonNull - public UpdateService.UpdateReceiver connectTo(@NonNull Peer peer, boolean requestSwapBack) { + public void connectTo(@NonNull Peer peer, boolean requestSwapBack) { if (peer != this.peer) { Log.e(TAG, "Oops, got a different peer to swap with than initially planned."); } @@ -172,7 +172,7 @@ public class SwapService extends Service { askServerToSwapWithUs(peerRepo); } - return UpdateService.updateRepoNow(peer.getRepoAddress(), this, false); + UpdateService.updateRepoNow(peer.getRepoAddress(), this); } private void askServerToSwapWithUs(final Repo repo) { diff --git a/F-Droid/src/org/fdroid/fdroid/net/ApkDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/ApkDownloader.java index 185f55bb1..98e76f0ba 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/ApkDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/ApkDownloader.java @@ -52,7 +52,6 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { public static final int ERROR_HASH_MISMATCH = 101; public static final int ERROR_DOWNLOAD_FAILED = 102; - public static final int ERROR_UNKNOWN = 103; private static final String EVENT_SOURCE_ID = "sourceId"; private static long downloadIdCounter = 0; @@ -63,14 +62,13 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { public static final String EVENT_DATA_ERROR_TYPE = "apkDownloadErrorType"; @NonNull private final Apk curApk; + @NonNull private final Context context; @NonNull private final String repoAddress; @NonNull private final SanitizedFile localFile; @NonNull private final SanitizedFile potentiallyCachedFile; private ProgressListener listener; private AsyncDownloadWrapper dlWrapper = null; - private int progress = 0; - private int totalSize = 0; private boolean isComplete = false; private final long id = ++downloadIdCounter; @@ -84,6 +82,7 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { } public ApkDownloader(@NonNull final Context context, @NonNull final Apk apk, @NonNull final String repoAddress) { + this.context = context; curApk = apk; this.repoAddress = repoAddress; localFile = new SanitizedFile(Utils.getApkDownloadDir(context), apk.apkName); @@ -191,7 +190,7 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { Log.d(TAG, "Downloading apk from " + remoteAddress + " to " + localFile); try { - Downloader downloader = DownloaderFactory.create(remoteAddress, localFile); + Downloader downloader = DownloaderFactory.create(context, remoteAddress, localFile); dlWrapper = new AsyncDownloadWrapper(downloader, this); dlWrapper.download(); return true; @@ -214,14 +213,6 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { } private void sendProgressEvent(Event event) { - switch (event.type) { - case Downloader.EVENT_PROGRESS: - // Keep a copy of these ourselves, so people can interrogate us for the - // info (in addition to receiving events with the info). - totalSize = event.total; - progress = event.progress; - break; - } event.getData().putLong(EVENT_SOURCE_ID, id); @@ -230,18 +221,6 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { } } - @Override - public void onReceiveTotalDownloadSize(int size) { - // Do nothing... - // Rather, we will obtain the total download size from the progress events - // when they start coming through. - } - - @Override - public void onReceiveCacheTag(String cacheTag) { - // Do nothing... - } - @Override public void onErrorDownloading(String localisedExceptionDetails) { Log.e(TAG, "Download failed: " + localisedExceptionDetails); @@ -292,7 +271,7 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener { public Apk getApk() { return curApk; } - public int getProgress() { return progress; } + public int getBytesRead() { return dlWrapper != null ? dlWrapper.getBytesRead() : 0; } - public int getTotalSize() { return totalSize; } + public int getTotalBytes() { return dlWrapper != null ? dlWrapper.getTotalBytes() : 0; } } diff --git a/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java b/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java index d113f93f3..3588343b8 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java +++ b/F-Droid/src/org/fdroid/fdroid/net/AsyncDownloadWrapper.java @@ -21,7 +21,6 @@ public class AsyncDownloadWrapper extends Handler { private static final String TAG = "AsyncDownloadWrapper"; - private static final int MSG_PROGRESS = 1; private static final int MSG_DOWNLOAD_COMPLETE = 2; private static final int MSG_DOWNLOAD_CANCELLED = 3; private static final int MSG_ERROR = 4; @@ -43,16 +42,6 @@ public class AsyncDownloadWrapper extends Handler { this.listener = listener; } - public void fetchTotalDownloadSize() { - int size = downloader.totalDownloadSize(); - listener.onReceiveTotalDownloadSize(size); - } - - public void fetchCacheTag() { - String cacheTag = downloader.getCacheTag(); - listener.onReceiveCacheTag(cacheTag); - } - public void download() { downloadThread = new DownloadThread(); downloadThread.start(); @@ -64,22 +53,6 @@ public class AsyncDownloadWrapper extends Handler { } } - public static class NotDownloadingException extends Exception { - public NotDownloadingException(String message) { - super(message); - } - } - - public void cancelDownload() throws NotDownloadingException { - if (downloadThread == null) { - throw new RuntimeException("Can't cancel download, it hasn't started yet."); - } else if (!downloadThread.isAlive()) { - throw new RuntimeException("Can't cancel download, it is already finished."); - } - - downloadThread.interrupt(); - } - /** * Receives "messages" from the download thread, and passes them onto the * relevant {@link org.fdroid.fdroid.net.AsyncDownloadWrapper.Listener} @@ -87,11 +60,6 @@ public class AsyncDownloadWrapper extends Handler { */ public void handleMessage(Message message) { switch (message.arg1) { - case MSG_PROGRESS: - Bundle data = message.getData(); - ProgressListener.Event event = data.getParcelable(MSG_DATA); - listener.onProgress(event); - break; case MSG_DOWNLOAD_COMPLETE: listener.onDownloadComplete(); break; @@ -104,19 +72,24 @@ public class AsyncDownloadWrapper extends Handler { } } + public int getBytesRead() { + return downloader.getBytesRead(); + } + + public int getTotalBytes() { + return downloader.getTotalBytes(); + } + public interface Listener extends ProgressListener { - void onReceiveTotalDownloadSize(int size); - void onReceiveCacheTag(String cacheTag); void onErrorDownloading(String localisedExceptionDetails); void onDownloadComplete(); void onDownloadCancelled(); } - private class DownloadThread extends Thread implements ProgressListener { + private class DownloadThread extends Thread { public void run() { try { - downloader.setProgressListener(this); downloader.download(); sendMessage(MSG_DOWNLOAD_COMPLETE); } catch (InterruptedException e) { @@ -137,16 +110,5 @@ public class AsyncDownloadWrapper extends Handler { message.arg1 = messageType; AsyncDownloadWrapper.this.sendMessage(message); } - - @Override - public void onProgress(Event event) { - Message message = new Message(); - Bundle data = new Bundle(); - data.putParcelable(MSG_DATA, event); - message.setData(data); - message.arg1 = MSG_PROGRESS; - AsyncDownloadWrapper.this.sendMessage(message); - } } - } diff --git a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java index a57039dfb..b9d6e2e40 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java @@ -10,11 +10,9 @@ import org.fdroid.fdroid.net.bluetooth.httpish.Request; import org.fdroid.fdroid.net.bluetooth.httpish.Response; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; +import java.net.URL; public class BluetoothDownloader extends Downloader { @@ -24,16 +22,10 @@ public class BluetoothDownloader extends Downloader { private FileDetails fileDetails; private final String sourcePath; - public BluetoothDownloader(String macAddress, String sourcePath, Context ctx) throws IOException { - super(ctx); + public BluetoothDownloader(Context context, String macAddress, URL sourceUrl, File destFile) throws IOException { + super(context, sourceUrl, destFile); this.connection = new BluetoothClient(macAddress).openConnection(); - this.sourcePath = sourcePath; - } - - public BluetoothDownloader(String macAddress, String sourcePath, File destFile) throws IOException { - super(destFile); - this.connection = new BluetoothClient(macAddress).openConnection(); - this.sourcePath = sourcePath; + this.sourcePath = sourceUrl.getPath(); } @Override diff --git a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java index 5cf34d630..18cb48946 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java @@ -1,11 +1,10 @@ package org.fdroid.fdroid.net; import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; +import android.content.Intent; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; -import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.Utils; import java.io.File; @@ -20,49 +19,31 @@ import java.net.URL; public abstract class Downloader { private static final String TAG = "Downloader"; - private OutputStream outputStream; - private ProgressListener progressListener = null; - private Bundle eventData = null; + public static final String LOCAL_ACTION_PROGRESS = "Downloader.PROGRESS"; + + public static final String EXTRA_ADDRESS = "extraAddress"; + public static final String EXTRA_BYTES_READ = "extraBytesRead"; + public static final String EXTRA_TOTAL_BYTES = "extraTotalBytes"; + + private final OutputStream outputStream; + + private final LocalBroadcastManager localBroadcastManager; private final File outputFile; - protected URL sourceUrl; + protected final URL sourceUrl; protected String cacheTag = null; - - public static final String EVENT_PROGRESS = "downloadProgress"; + protected int bytesRead = 0; + protected int totalBytes = 0; public abstract InputStream getInputStream() throws IOException; - // The context is required for opening the file to write to. - Downloader(String destFile, @NonNull Context ctx) - throws FileNotFoundException, MalformedURLException { - this(new File(ctx.getFilesDir() + File.separator + destFile)); - } - - // The context is required for opening the file to write to. - Downloader(@NonNull Context ctx) throws IOException { - this(File.createTempFile("dl-", "", ctx.getCacheDir())); - } - - Downloader(File destFile) + Downloader(Context context, URL url, File destFile) throws FileNotFoundException, MalformedURLException { + this.sourceUrl = url; outputFile = destFile; outputStream = new FileOutputStream(outputFile); - } - - Downloader(OutputStream output) - throws MalformedURLException { - outputStream = output; - outputFile = null; - } - - public void setProgressListener(ProgressListener listener) { - setProgressListener(listener, null); - } - - public void setProgressListener(ProgressListener listener, Bundle eventData) { - this.progressListener = listener; - this.eventData = eventData; + localBroadcastManager = LocalBroadcastManager.getInstance(context); } /** @@ -157,11 +138,16 @@ public abstract class Downloader { } } + /** + * This copies the downloaded data from the InputStream to the OutputStream, + * keeping track of the number of bytes that have flowed through for the + * progress counter. + */ protected void copyInputToOutputStream(InputStream input) throws IOException, InterruptedException { byte[] buffer = new byte[Utils.BUFFER_SIZE]; int bytesRead = 0; - int totalBytes = totalDownloadSize(); + this.totalBytes = totalDownloadSize(); // Getting the total download size could potentially take time, depending on how // it is implemented, so we may as well check this before we proceed. @@ -186,13 +172,19 @@ public abstract class Downloader { } protected void sendProgress(int bytesRead, int totalBytes) { - sendProgress(new ProgressListener.Event(EVENT_PROGRESS, bytesRead, totalBytes, eventData)); + this.bytesRead = bytesRead; + Intent intent = new Intent(LOCAL_ACTION_PROGRESS); + intent.putExtra(EXTRA_ADDRESS, sourceUrl.toString()); + intent.putExtra(EXTRA_BYTES_READ, bytesRead); + intent.putExtra(EXTRA_TOTAL_BYTES, totalBytes); + localBroadcastManager.sendBroadcast(intent); } - protected void sendProgress(ProgressListener.Event event) { - if (progressListener != null) { - progressListener.onProgress(event); - } + public int getBytesRead() { + return bytesRead; } + public int getTotalBytes() { + return totalBytes; + } } diff --git a/F-Droid/src/org/fdroid/fdroid/net/DownloaderFactory.java b/F-Droid/src/org/fdroid/fdroid/net/DownloaderFactory.java index 6c99584e4..5b476dd1c 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/DownloaderFactory.java +++ b/F-Droid/src/org/fdroid/fdroid/net/DownloaderFactory.java @@ -1,42 +1,57 @@ package org.fdroid.fdroid.net; import android.content.Context; -import android.net.Uri; import java.io.File; import java.io.IOException; +import java.net.URL; public class DownloaderFactory { - public static Downloader create(String url, Context context) throws IOException { - Uri uri = Uri.parse(url); - if (isBluetoothAddress(uri)) { - String macAddress = uri.getHost().replace("-", ":"); - return new BluetoothDownloader(macAddress, uri.getPath(), context); + /** + * Downloads to a temporary file, which *you must delete yourself when + * you are done. It is stored in {@link Context#getCacheDir()} and starts + * with the prefix {@code dl-}. + */ + public static Downloader create(Context context, String urlString) + throws IOException { + return create(context, new URL(urlString)); + } + + /** + * Downloads to a temporary file, which *you must delete yourself when + * you are done. It is stored in {@link Context#getCacheDir()} and starts + * with the prefix {@code dl-}. + */ + public static Downloader create(Context context, URL url) + throws IOException { + File destFile = File.createTempFile("dl-", "", context.getCacheDir()); + destFile.deleteOnExit(); // this probably does nothing, but maybe... + return create(context, url, destFile); + } + + public static Downloader create(Context context, String urlString, File destFile) + throws IOException { + return create(context, new URL(urlString), destFile); + } + + public static Downloader create(Context context, URL url, File destFile) + throws IOException { + if (isBluetoothAddress(url)) { + String macAddress = url.getHost().replace("-", ":"); + return new BluetoothDownloader(context, macAddress, url, destFile); } else if (isOnionAddress(url)) { - return new TorHttpDownloader(url, context); + return new TorHttpDownloader(context, url, destFile); } else { - return new HttpDownloader(url, context); + return new HttpDownloader(context, url, destFile); } } - public static Downloader create(String url, File destFile) throws IOException { - Uri uri = Uri.parse(url); - if (isBluetoothAddress(uri)) { - String macAddress = uri.getHost().replace("-", ":"); - return new BluetoothDownloader(macAddress, uri.getPath(), destFile); - } else if (isOnionAddress(url)) { - return new TorHttpDownloader(url, destFile); - } else { - return new HttpDownloader(url, destFile); - } + private static boolean isBluetoothAddress(URL url) { + return "bluetooth".equalsIgnoreCase(url.getProtocol()); } - private static boolean isBluetoothAddress(Uri uri) { - return "bluetooth".equalsIgnoreCase(uri.getScheme()); - } - - private static boolean isOnionAddress(String url) { - return url.matches("^[a-zA-Z0-9]+://[^/]+\\.onion/.*"); + private static boolean isOnionAddress(URL url) { + return url.getHost().endsWith(".onion"); } } diff --git a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java index c9f76249e..c091fd607 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java @@ -29,21 +29,9 @@ public class HttpDownloader extends Downloader { private int statusCode = -1; private boolean onlyStream = false; - // The context is required for opening the file to write to. - HttpDownloader(String source, File destFile) + HttpDownloader(Context context, URL url, File destFile) throws FileNotFoundException, MalformedURLException { - super(destFile); - sourceUrl = new URL(source); - } - - /** - * Downloads to a temporary file, which *you must delete yourself when - * you are done*. - * @see org.fdroid.fdroid.net.Downloader#getFile() - */ - public HttpDownloader(String source, Context ctx) throws IOException { - super(ctx); - sourceUrl = new URL(source); + super(context, url, destFile); } /** diff --git a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java index 0ba464755..b90876df8 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java @@ -22,7 +22,7 @@ public class IconDownloader extends BaseImageDownloader { switch (Scheme.ofUri(imageUri)) { case HTTP: case HTTPS: - Downloader downloader = DownloaderFactory.create(imageUri, context); + Downloader downloader = DownloaderFactory.create(context, imageUri); return downloader.getInputStream(); default: return super.getStream(imageUri, extra); diff --git a/F-Droid/src/org/fdroid/fdroid/net/TorHttpDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/TorHttpDownloader.java index 70848ac66..c0eaf4d45 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/TorHttpDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/TorHttpDownloader.java @@ -10,16 +10,13 @@ import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Proxy; import java.net.SocketAddress; +import java.net.URL; public class TorHttpDownloader extends HttpDownloader { - TorHttpDownloader(String url, Context ctx) throws IOException { - super(url, ctx); - } - - TorHttpDownloader(String url, File destFile) + TorHttpDownloader(Context context, URL url, File destFile) throws FileNotFoundException, MalformedURLException { - super(url, destFile); + super(context, url, destFile); } @Override diff --git a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java index 5bea61a1d..dae0644c8 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java @@ -19,7 +19,6 @@ package org.fdroid.fdroid.views; -import android.app.AlertDialog; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; @@ -42,6 +41,7 @@ import android.support.v4.app.NavUtils; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -64,14 +64,12 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.fdroid.fdroid.FDroid; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; -import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.compat.ClipboardCompat; import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.RepoProvider; -import org.fdroid.fdroid.views.fragments.RepoDetailsFragment; import java.io.IOException; import java.net.MalformedURLException; @@ -82,13 +80,6 @@ import java.util.Date; import java.util.Locale; public class ManageReposActivity extends ActionBarActivity { - - /** - * If we have a new repo added, or the address of a repo has changed, then - * we when we're finished, we'll set this boolean to true in the intent that - * we finish with, to signify that we want the main list of apps updated. - */ - public static final String REQUEST_UPDATE = "update"; private static final String TAG = "ManageReposActivity"; private static final String DEFAULT_NEW_REPO_TEXT = "https://"; @@ -99,10 +90,6 @@ public class ManageReposActivity extends ActionBarActivity { IS_SWAP } - private UpdateService.UpdateReceiver updateHandler = null; - - private static boolean changed = false; - private RepoListFragment listFragment; /** @@ -147,21 +134,11 @@ public class ManageReposActivity extends ActionBarActivity { @Override protected void onResume() { super.onResume(); - if (updateHandler != null) { - updateHandler.showDialog(); - } + /* let's see if someone is trying to send us a new repo */ addRepoFromIntent(getIntent()); } - @Override - protected void onPause() { - super.onPause(); - if (updateHandler != null) { - updateHandler.hideDialog(); - } - } - @Override protected void onNewIntent(Intent intent) { setIntent(intent); @@ -170,22 +147,10 @@ public class ManageReposActivity extends ActionBarActivity { @Override public void finish() { Intent ret = new Intent(); - markChangedIfRequired(ret); setResult(RESULT_OK, ret); super.finish(); } - private boolean hasChanged() { - return changed; - } - - private void markChangedIfRequired(Intent intent) { - if (hasChanged()) { - Log.i(TAG, "Repo details have changed, prompting for update."); - intent.putExtra(REQUEST_UPDATE, true); - } - } - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.manage_repos, menu); @@ -197,7 +162,6 @@ public class ManageReposActivity extends ActionBarActivity { switch (item.getItemId()) { case android.R.id.home: Intent destIntent = new Intent(this, FDroid.class); - markChangedIfRequired(destIntent); setResult(RESULT_OK, destIntent); NavUtils.navigateUpTo(this, destIntent); return true; @@ -205,32 +169,12 @@ public class ManageReposActivity extends ActionBarActivity { showAddRepo(); return true; case R.id.action_update_repo: - updateRepos(); + UpdateService.updateNow(this); return true; } return super.onOptionsItemSelected(item); } - private void updateRepos() { - updateHandler = UpdateService.updateNow(this).setListener( - new ProgressListener() { - @Override - public void onProgress(Event event) { - switch (event.type) { - case UpdateService.EVENT_COMPLETE_AND_SAME: - case UpdateService.EVENT_COMPLETE_WITH_CHANGES: - // No need to prompt to update any more, we just - // did it! - changed = false; - break; - case UpdateService.EVENT_FINISHED: - updateHandler = null; - break; - } - } - }); - } - private void showAddRepo() { /* * If there is text in the clipboard, and it looks like a URL, use that. @@ -291,9 +235,7 @@ public class ManageReposActivity extends ActionBarActivity { final EditText uriEditText = (EditText) view.findViewById(R.id.edit_uri); final EditText fingerprintEditText = (EditText) view.findViewById(R.id.edit_fingerprint); - addRepoDialog.setIcon(android.R.drawable.ic_menu_add); addRepoDialog.setTitle(getString(R.string.repo_add_title)); - addRepoDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), new DialogInterface.OnClickListener() { @@ -651,11 +593,11 @@ public class ManageReposActivity extends ActionBarActivity { /** * If started by an intent that expects a result (e.g. QR codes) then we - * will set a result and finish. Otherwise, we'll refresh the list of repos + * will set a result and finish. Otherwise, we'll updateViews the list of repos * to reflect the newly created repo. */ private void finishedAddingRepo() { - changed = true; + UpdateService.updateNow(ManageReposActivity.this); if (addRepoDialog.isShowing()) { addRepoDialog.dismiss(); } @@ -728,7 +670,7 @@ public class ManageReposActivity extends ActionBarActivity { /** * NOTE: If somebody toggles a repo off then on again, it will have * removed all apps from the index when it was toggled off, so when it - * is toggled on again, then it will require a refresh. Previously, I + * is toggled on again, then it will require a updateViews. Previously, I * toyed with the idea of remembering whether they had toggled on or * off, and then only actually performing the function when the activity * stopped, but I think that will be problematic. What about when they @@ -748,7 +690,7 @@ public class ManageReposActivity extends ActionBarActivity { RepoProvider.Helper.update(getActivity(), repo, values); if (isEnabled) { - changed = true; + UpdateService.updateNow(getActivity()); } else { FDroidApp app = (FDroidApp) getActivity().getApplication(); RepoProvider.Helper.purgeApps(getActivity(), repo, app); @@ -833,7 +775,7 @@ public class ManageReposActivity extends ActionBarActivity { public void editRepo(Repo repo) { Intent intent = new Intent(getActivity(), RepoDetailsActivity.class); - intent.putExtra(RepoDetailsFragment.ARG_REPO_ID, repo.getId()); + intent.putExtra(RepoDetailsActivity.ARG_REPO_ID, repo.getId()); startActivityForResult(intent, SHOW_REPO_DETAILS); } diff --git a/F-Droid/src/org/fdroid/fdroid/views/RepoDetailsActivity.java b/F-Droid/src/org/fdroid/fdroid/views/RepoDetailsActivity.java index 51e965828..c49325c45 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/RepoDetailsActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/RepoDetailsActivity.java @@ -1,33 +1,91 @@ package org.fdroid.fdroid.views; import android.annotation.TargetApi; +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.net.Uri; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; +import android.support.v7.app.AlertDialog; import android.support.v4.app.NavUtils; +import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.ActionBarActivity; +import android.text.TextUtils; import android.util.Log; +import android.view.Menu; import android.view.MenuItem; -import android.widget.LinearLayout; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; import android.widget.Toast; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.NfcHelper; +import org.fdroid.fdroid.NfcNotEnabledActivity; +import org.fdroid.fdroid.QrGenAsyncTask; +import org.fdroid.fdroid.R; +import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.RepoProvider; -import org.fdroid.fdroid.views.fragments.RepoDetailsFragment; + +import java.util.Locale; public class RepoDetailsActivity extends ActionBarActivity { private static final String TAG = "RepoDetailsActivity"; - private Repo repo; + public static final String MIME_TYPE = "application/vnd.org.fdroid.fdroid.repo"; + public static final String ARG_REPO_ID = "repo_id"; - static final String MIME_TYPE = "application/vnd.org.fdroid.fdroid.repo"; + /** + * If the repo has been updated at least once, then we will show + * all of this info, otherwise they will be hidden. + */ + private static final int[] SHOW_IF_EXISTS = { + R.id.label_repo_name, + R.id.text_repo_name, + R.id.label_description, + R.id.text_description, + R.id.label_num_apps, + R.id.text_num_apps, + R.id.label_last_update, + R.id.text_last_update, + R.id.label_repo_fingerprint, + R.id.text_repo_fingerprint, + R.id.text_repo_fingerprint_description + }; + /** + * If the repo has <em>not</em> been updated yet, then we only show + * these, otherwise they are hidden. + */ + private static final int[] HIDE_IF_EXISTS = { + R.id.text_not_yet_updated, + R.id.btn_update + }; + private Repo repo; + private long repoId; + private View repoView; + + /** + * Help function to make switching between two view states easier. + * Perhaps there is a better way to do this. I recall that using Adobe + * Flex, there was a thing called "ViewStates" for exactly this. Wonder if + * that exists in Android? + */ + private static void setMultipleViewVisibility(View parent, + int[] viewIds, + int visibility) { + for (int viewId : viewIds) { + parent.findViewById(viewId).setVisibility(visibility); + } + } @Override protected void onCreate(Bundle savedInstanceState) { @@ -35,27 +93,11 @@ public class RepoDetailsActivity extends ActionBarActivity { ((FDroidApp) getApplication()).applyTheme(this); super.onCreate(savedInstanceState); - long repoId = getIntent().getLongExtra(RepoDetailsFragment.ARG_REPO_ID, 0); - - if (savedInstanceState == null) { - - // Need to set a dummy view (which will get overridden by the fragment manager - // below) so that we can call setContentView(). This is a work around for - // a (bug?) thing in 3.0, 3.1 which requires setContentView to be invoked before - // the actionbar is played with: - // http://blog.perpetumdesign.com/2011/08/strange-case-of-dr-action-and-mr-bar.html - if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) { - setContentView(new LinearLayout(this)); - } - - RepoDetailsFragment fragment = new RepoDetailsFragment(); - fragment.setArguments(getIntent().getExtras()); - getSupportFragmentManager() - .beginTransaction() - .add(android.R.id.content, fragment) - .commit(); - } + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + setContentView(R.layout.repodetails); + repoView = findViewById(R.id.repoView); + repoId = getIntent().getLongExtra(ARG_REPO_ID, 0); final String[] projection = { RepoProvider.DataColumns.NAME, RepoProvider.DataColumns.ADDRESS, @@ -63,8 +105,23 @@ public class RepoDetailsActivity extends ActionBarActivity { }; repo = RepoProvider.Helper.findById(this, repoId, projection); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - setTitle(repo.getName()); + setTitle(repo.name); + + TextView inputUrl = (TextView) findViewById(R.id.input_repo_url); + inputUrl.setText(repo.address); + + Button update = (Button) repoView.findViewById(R.id.btn_update); + update.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + performUpdate(); + } + }); + + Uri uri = Uri.parse(repo.address); + uri = uri.buildUpon().appendQueryParameter("fingerprint", repo.fingerprint).build(); + String qrUriString = uri.toString().toUpperCase(Locale.ENGLISH); + new QrGenAsyncTask(this, R.id.qr_code).execute(uri.toString()); } @TargetApi(14) @@ -82,6 +139,19 @@ public class RepoDetailsActivity extends ActionBarActivity { @Override public void onResume() { super.onResume(); + + /* + * After, for example, a repo update, the details will have changed in the + * database. However, or local reference to the Repo object will not + * have been updated. The safest way to deal with this is to reload the + * repo object directly from the database. + */ + repo = RepoProvider.Helper.findById(this, repoId); + updateRepoView(); + + LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, + new IntentFilter(UpdateService.LOCAL_ACTION_STATUS)); + // FDroid.java and AppDetails set different NFC actions, so reset here setNfc(); processIntent(getIntent()); @@ -105,21 +175,189 @@ public class RepoDetailsActivity extends ActionBarActivity { Log.i(TAG, "Got this URL: " + url); Toast.makeText(this, "Got this URL: " + url, Toast.LENGTH_LONG).show(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - String packageName = getPackageName(); - intent.setClassName(packageName, packageName + ".ManageRepo"); + intent.setClass(this, ManageReposActivity.class); startActivity(intent); finish(); } } + private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int statusCode = intent.getIntExtra(UpdateService.EXTRA_STATUS_CODE, -1); + if (statusCode == UpdateService.STATUS_COMPLETE_WITH_CHANGES) + updateRepoView(); + } + }; + + @Override + protected void onPause() { + super.onPause(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.repo_details_activity, menu); + return true; + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - return true; + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + return true; + case R.id.menu_update: + performUpdate(); + return true; + case R.id.menu_delete: + promptForDelete(); + return true; + case R.id.menu_enable_nfc: + Intent intent = new Intent(this, NfcNotEnabledActivity.class); + startActivity(intent); + return true; } + return super.onOptionsItemSelected(item); } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (Build.VERSION.SDK_INT >= 14) { + prepareNfcMenuItems(menu); + } + return true; + } + + @TargetApi(16) + private void prepareNfcMenuItems(Menu menu) { + NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); + if (nfcAdapter == null) { + return; + } + + boolean needsEnableNfcMenuItem; + if (Build.VERSION.SDK_INT < 16) { + needsEnableNfcMenuItem = !nfcAdapter.isEnabled(); + } else { + needsEnableNfcMenuItem = !nfcAdapter.isNdefPushEnabled(); + } + + MenuItem menuItem = menu.findItem(R.id.menu_enable_nfc); + menuItem.setVisible(needsEnableNfcMenuItem); + } + + private void setupDescription(View parent, Repo repo) { + + TextView descriptionLabel = (TextView) parent.findViewById(R.id.label_description); + TextView description = (TextView) parent.findViewById(R.id.text_description); + + if (TextUtils.isEmpty(repo.description)) { + descriptionLabel.setVisibility(View.GONE); + description.setVisibility(View.GONE); + description.setText(""); + } else { + descriptionLabel.setVisibility(View.VISIBLE); + description.setVisibility(View.VISIBLE); + description.setText(repo.description.replaceAll("\n", " ")); + } + } + + private void setupRepoFingerprint(View parent, Repo repo) { + TextView repoFingerprintView = (TextView) parent.findViewById(R.id.text_repo_fingerprint); + TextView repoFingerprintDescView = (TextView) parent.findViewById(R.id.text_repo_fingerprint_description); + + String repoFingerprint; + int repoFingerprintColor; + + // TODO show the current state of the signature check, not just whether there is a key or not + if (TextUtils.isEmpty(repo.fingerprint) && TextUtils.isEmpty(repo.pubkey)) { + repoFingerprint = getResources().getString(R.string.unsigned); + repoFingerprintColor = getResources().getColor(R.color.unsigned); + repoFingerprintDescView.setVisibility(View.VISIBLE); + repoFingerprintDescView.setText(getResources().getString(R.string.unsigned_description)); + } else { + // this is based on repo.fingerprint always existing, which it should + repoFingerprint = Utils.formatFingerprint(this, repo.fingerprint); + repoFingerprintColor = getResources().getColor(R.color.signed); + repoFingerprintDescView.setVisibility(View.GONE); + } + + repoFingerprintView.setText(repoFingerprint); + repoFingerprintView.setTextColor(repoFingerprintColor); + } + + private void updateRepoView() { + + if (repo.hasBeenUpdated()) { + updateViewForExistingRepo(repoView); + } else { + updateViewForNewRepo(repoView); + } + + } + + private void updateViewForNewRepo(View repoView) { + setMultipleViewVisibility(repoView, HIDE_IF_EXISTS, View.VISIBLE); + setMultipleViewVisibility(repoView, SHOW_IF_EXISTS, View.GONE); + } + + private void updateViewForExistingRepo(View repoView) { + setMultipleViewVisibility(repoView, SHOW_IF_EXISTS, View.VISIBLE); + setMultipleViewVisibility(repoView, HIDE_IF_EXISTS, View.GONE); + + TextView name = (TextView) repoView.findViewById(R.id.text_repo_name); + TextView numApps = (TextView) repoView.findViewById(R.id.text_num_apps); + TextView lastUpdated = (TextView) repoView.findViewById(R.id.text_last_update); + + name.setText(repo.name); + + int appCount = RepoProvider.Helper.countAppsForRepo(this, repoId); + numApps.setText(Integer.toString(appCount)); + + setupDescription(repoView, repo); + setupRepoFingerprint(repoView, repo); + + // Repos that existed before this feature was supported will have an + // "Unknown" last update until next time they update... + String lastUpdate = repo.lastUpdated != null + ? repo.lastUpdated.toString() : getString(R.string.unknown); + lastUpdated.setText(lastUpdate); + } + + /** + * When an update is performed, notify the listener so that the repo + * list can be updated. We will perform the update ourselves though. + */ + private void performUpdate() { + // Ensure repo is enabled before updating... + ContentValues values = new ContentValues(1); + values.put(RepoProvider.DataColumns.IN_USE, 1); + RepoProvider.Helper.update(this, repo, values); + + UpdateService.updateRepoNow(repo.address, this); + } + + private void promptForDelete() { + new AlertDialog.Builder(this) + .setTitle(R.string.repo_confirm_delete_title) + .setMessage(R.string.repo_confirm_delete_body) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + RepoProvider.Helper.remove(getApplicationContext(), repoId); + finish(); + } + }).setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Do nothing... + } + } + ).show(); + } + } diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java index fa155c5eb..47c8c207e 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java @@ -138,7 +138,7 @@ public class CanUpdateAppsFragment extends AppListFragment { mUpdateAllButton.setId(UPDATE_ALL_BUTTON_ID); mUpdateAllButton.setText(R.string.update_all); mUpdateAllButton.setCompoundDrawablesWithIntrinsicBounds( - getResources().getDrawable(R.drawable.ic_menu_refresh), null, null, null); + getResources().getDrawable(R.drawable.ic_refresh_white), null, null, null); mUpdateAllButton.setVisibility(View.GONE); linearLayout.addView(mUpdateAllButton, new FrameLayout.LayoutParams( diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java index d5d359a03..f0c84ba1b 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/PreferencesFragment.java @@ -1,6 +1,5 @@ package org.fdroid.fdroid.views.fragments; -import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -11,6 +10,7 @@ import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.support.v4.preference.PreferenceFragment; +import android.support.v7.app.AlertDialog; import android.text.Html; import android.text.TextUtils; diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java deleted file mode 100644 index 04876d8d2..000000000 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/RepoDetailsFragment.java +++ /dev/null @@ -1,393 +0,0 @@ -package org.fdroid.fdroid.views.fragments; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ContentValues; -import android.content.DialogInterface; -import android.content.Intent; -import android.nfc.NfcAdapter; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.view.MenuItemCompat; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.TextView; - -import org.fdroid.fdroid.NfcNotEnabledActivity; -import org.fdroid.fdroid.ProgressListener; -import org.fdroid.fdroid.R; -import org.fdroid.fdroid.UpdateService; -import org.fdroid.fdroid.Utils; -import org.fdroid.fdroid.data.Repo; -import org.fdroid.fdroid.data.RepoProvider; - -public class RepoDetailsFragment extends Fragment { - - public static final String ARG_REPO_ID = "repo_id"; - - /** - * If the repo has been updated at least once, then we will show - * all of this info, otherwise they will be hidden. - */ - private static final int[] SHOW_IF_EXISTS = { - R.id.label_repo_name, - R.id.text_repo_name, - R.id.label_description, - R.id.text_description, - R.id.label_num_apps, - R.id.text_num_apps, - R.id.label_last_update, - R.id.text_last_update, - R.id.label_repo_fingerprint, - R.id.text_repo_fingerprint, - R.id.text_repo_fingerprint_description - }; - - /** - * If the repo has <em>not</em> been updated yet, then we only show - * these, otherwise they are hidden. - */ - private static final int[] HIDE_IF_EXISTS = { - R.id.text_not_yet_updated, - R.id.btn_update - }; - - private static final int DELETE = 0; - private static final int UPDATE = 1; - private static final int ENABLE_NFC = 2; - - private static final String TAG = "RepoDetailsFragment"; - - private MenuItem enableNfc = null; - private UpdateService.UpdateReceiver updateHandler = null; - - // TODO: Currently initialised in onCreateView. Not sure if that is the - // best way to go about this... - private Repo repo; - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - if (updateHandler != null) { - updateHandler.showDialog(); - } - } - - @Override - public void onDetach() { - super.onDetach(); - if (updateHandler != null) { - updateHandler.hideDialog(); - } - } - - private long getRepoId() { - return getArguments().getLong(RepoDetailsFragment.ARG_REPO_ID, 0); - } - - /** - * After, for example, a repo update, the details will have changed in the - * database. However, or local reference to the Repo object will not - * have been updated. The safest way to deal with this is to reload the - * repo object directly from the database. - */ - private Repo loadRepoDetails() { - return RepoProvider.Helper.findById(getActivity(), getRepoId()); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - repo = loadRepoDetails(); - - if (repo == null) { - Log.e(TAG, "Error showing details for repo '" + getRepoId() + "'"); - return new LinearLayout(container.getContext()); - } - - ViewGroup repoView = (ViewGroup)inflater.inflate(R.layout.repodetails, null); - updateView(repoView); - - // Setup listeners here, rather than in updateView(...), - // because otherwise we will end up adding multiple listeners with - // subsequent calls to updateView(). - EditText inputUrl = (EditText)repoView.findViewById(R.id.input_repo_url); - inputUrl.addTextChangedListener(new UrlWatcher()); - - Button update = (Button)repoView.findViewById(R.id.btn_update); - update.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - performUpdate(); - } - }); - - return repoView; - } - - /** - * Populates relevant views with properties from the current repository. - * Decides which views to show and hide depending on the state of the - * repository. - */ - private void updateView(ViewGroup repoView) { - - EditText inputUrl = (EditText)repoView.findViewById(R.id.input_repo_url); - inputUrl.setText(repo.address); - - if (repo.hasBeenUpdated()) { - updateViewForExistingRepo(repoView); - } else { - updateViewForNewRepo(repoView); - } - - } - - /** - * Help function to make switching between two view states easier. - * Perhaps there is a better way to do this. I recall that using Adobe - * Flex, there was a thing called "ViewStates" for exactly this. Wonder if - * that exists in Android? - */ - private static void setMultipleViewVisibility(ViewGroup parent, - int[] viewIds, - int visibility) { - for (int viewId : viewIds) { - parent.findViewById(viewId).setVisibility(visibility); - } - } - - private void updateViewForNewRepo(ViewGroup repoView) { - setMultipleViewVisibility(repoView, HIDE_IF_EXISTS, View.VISIBLE); - setMultipleViewVisibility(repoView, SHOW_IF_EXISTS, View.GONE); - } - - private void updateViewForExistingRepo(ViewGroup repoView) { - setMultipleViewVisibility(repoView, SHOW_IF_EXISTS, View.VISIBLE); - setMultipleViewVisibility(repoView, HIDE_IF_EXISTS, View.GONE); - - TextView name = (TextView)repoView.findViewById(R.id.text_repo_name); - TextView numApps = (TextView)repoView.findViewById(R.id.text_num_apps); - TextView lastUpdated = (TextView)repoView.findViewById(R.id.text_last_update); - - name.setText(repo.getName()); - - int appCount = RepoProvider.Helper.countAppsForRepo(getActivity(), repo.getId()); - numApps.setText(Integer.toString(appCount)); - - setupDescription(repoView, repo); - setupRepoFingerprint(repoView, repo); - - // Repos that existed before this feature was supported will have an - // "Unknown" last update until next time they update... - String lastUpdate = repo.lastUpdated != null - ? repo.lastUpdated.toString() : getString(R.string.unknown); - lastUpdated.setText(lastUpdate); - } - - private void setupDescription(ViewGroup parent, Repo repo) { - - TextView descriptionLabel = (TextView)parent.findViewById(R.id.label_description); - TextView description = (TextView)parent.findViewById(R.id.text_description); - - if (repo.description == null || repo.description.length() == 0) { - descriptionLabel.setVisibility(View.GONE); - description.setVisibility(View.GONE); - } else { - descriptionLabel.setVisibility(View.VISIBLE); - description.setVisibility(View.VISIBLE); - } - - String descriptionText = repo.description == null - ? "" : repo.description.replaceAll("\n", " "); - description.setText(descriptionText); - - } - - /** - * When an update is performed, notify the listener so that the repo - * list can be updated. We will perform the update ourselves though. - */ - private void performUpdate() { - // Ensure repo is enabled before updating... - ContentValues values = new ContentValues(1); - values.put(RepoProvider.DataColumns.IN_USE, 1); - RepoProvider.Helper.update(getActivity(), repo, values); - - updateHandler = UpdateService.updateRepoNow(repo.address, getActivity()).setListener(new ProgressListener() { - @Override - public void onProgress(Event event) { - switch (event.type) { - case UpdateService.EVENT_COMPLETE_WITH_CHANGES: - repo = loadRepoDetails(); - updateView((ViewGroup)getView()); - break; - case UpdateService.EVENT_FINISHED: - updateHandler = null; - break; - } - } - }); - } - - /** - * When the URL is changed, notify the repoChangeListener. - */ - class UrlWatcher implements TextWatcher { - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void afterTextChanged(Editable s) {} - - @Override - // TODO: This is called each character change, resulting in a DB query. - // Doesn't exactly cause performance problems, - // but seems silly not to go for more of a "focus out" event then - // this "text changed" event. - public void onTextChanged(CharSequence s, int start, int before, int count) { - if (!repo.address.equals(s.toString())) { - ContentValues values = new ContentValues(1); - values.put(RepoProvider.DataColumns.ADDRESS, s.toString()); - RepoProvider.Helper.update(getActivity(), repo, values); - } - } - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - menu.clear(); - - MenuItem update = menu.add(Menu.NONE, UPDATE, 0, R.string.repo_update); - update.setIcon(R.drawable.ic_refresh_white); - MenuItemCompat.setShowAsAction(update, - MenuItemCompat.SHOW_AS_ACTION_ALWAYS | - MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT); - - MenuItem delete = menu.add(Menu.NONE, DELETE, 0, R.string.delete); - delete.setIcon(R.drawable.ic_delete_white); - MenuItemCompat.setShowAsAction(delete, - MenuItemCompat.SHOW_AS_ACTION_IF_ROOM | - MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT); - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - if (Build.VERSION.SDK_INT >= 14) - prepareNfcMenuItems(menu); - } - - @TargetApi(16) - private void prepareNfcMenuItems(Menu menu) { - boolean needsEnableNfcMenuItem; - NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity()); - if (nfcAdapter == null) { - return; - } - if (Build.VERSION.SDK_INT < 16) - needsEnableNfcMenuItem = !nfcAdapter.isEnabled(); - else - needsEnableNfcMenuItem = !nfcAdapter.isNdefPushEnabled(); - if (needsEnableNfcMenuItem) { - if (enableNfc != null) - return; // already created - enableNfc = menu.add(Menu.NONE, ENABLE_NFC, 0, R.string.enable_nfc_send); - enableNfc.setIcon(R.drawable.ic_nfc_white); - MenuItemCompat.setShowAsAction(enableNfc, - MenuItemCompat.SHOW_AS_ACTION_IF_ROOM | - MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT); - } else if (enableNfc != null) { - // remove the existing MenuItem since NFC is now enabled - menu.removeItem(enableNfc.getItemId()); - enableNfc = null; - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case DELETE: - promptForDelete(); - return true; - case UPDATE: - performUpdate(); - return true; - case ENABLE_NFC: - Intent intent = new Intent(getActivity(), NfcNotEnabledActivity.class); - startActivity(intent); - return true; - } - - return false; - } - - private void promptForDelete() { - new AlertDialog.Builder(getActivity()) - .setTitle(R.string.repo_confirm_delete_title) - .setIcon(android.R.drawable.ic_menu_delete) - .setMessage(R.string.repo_confirm_delete_body) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Repo repo = RepoDetailsFragment.this.repo; - RepoProvider.Helper.remove(getActivity(), repo.getId()); - getActivity().finish(); - } - }).setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Do nothing... - } - } - ).show(); - } - - private void setupRepoFingerprint(ViewGroup parent, Repo repo) { - TextView repoFingerprintView = (TextView)parent.findViewById(R.id.text_repo_fingerprint); - TextView repoFingerprintDescView = (TextView)parent.findViewById(R.id.text_repo_fingerprint_description); - - String repoFingerprint; - int repoFingerprintColor; - - // TODO show the current state of the signature check, not just whether there is a key or not - if (TextUtils.isEmpty(repo.fingerprint) && TextUtils.isEmpty(repo.pubkey)) { - repoFingerprint = getResources().getString(R.string.unsigned); - repoFingerprintColor = getResources().getColor(R.color.unsigned); - repoFingerprintDescView.setVisibility(View.VISIBLE); - repoFingerprintDescView.setText(getResources().getString(R.string.unsigned_description)); - } else { - // this is based on repo.fingerprint always existing, which it should - repoFingerprint = Utils.formatFingerprint(getActivity(), repo.fingerprint); - repoFingerprintColor = getResources().getColor(R.color.signed); - repoFingerprintDescView.setVisibility(View.GONE); - } - - repoFingerprintView.setText(repoFingerprint); - repoFingerprintView.setTextColor(repoFingerprintColor); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - setRetainInstance(true); - } - -} diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java index 6f91d4e78..45d25ea16 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -1,7 +1,9 @@ package org.fdroid.fdroid.views.swap; import android.annotation.TargetApi; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -14,6 +16,7 @@ import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.SearchView; @@ -35,7 +38,6 @@ import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; -import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; @@ -115,6 +117,8 @@ public class SwapAppsView extends ListView implements schedulePollForUpdates(); } + private BroadcastReceiver pollForUpdatesReceiver; + private void pollForUpdates() { if (adapter.getCount() > 1 || (adapter.getCount() == 1 && !new App((Cursor)adapter.getItem(0)).id.equals("org.fdroid.fdroid"))) { @@ -123,13 +127,14 @@ public class SwapAppsView extends ListView implements } Log.d(TAG, "Polling swap repo to see if it has any updates."); - UpdateService.UpdateReceiver receiver = getState().refreshSwap(); - if (receiver != null) { - receiver.setListener(new ProgressListener() { + getState().refreshSwap(); + if (pollForUpdatesReceiver != null) { + pollForUpdatesReceiver = new BroadcastReceiver() { @Override - public void onProgress(Event event) { - switch (event.type) { - case UpdateService.EVENT_COMPLETE_WITH_CHANGES: + public void onReceive(Context context, Intent intent) { + int statusCode = intent.getIntExtra(UpdateService.EXTRA_STATUS_CODE, -1); + switch (statusCode) { + case UpdateService.STATUS_COMPLETE_WITH_CHANGES: Log.d(TAG, "Swap repo has updates, notifying the list adapter."); getActivity().runOnUiThread(new Runnable() { @Override @@ -137,19 +142,22 @@ public class SwapAppsView extends ListView implements adapter.notifyDataSetChanged(); } }); + LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(pollForUpdatesReceiver); break; - case UpdateService.EVENT_ERROR: + case UpdateService.STATUS_ERROR_GLOBAL: // TODO: Well, if we can't get the index, we probably can't swapp apps. // Tell the user somethign helpful? break; - case UpdateService.EVENT_COMPLETE_AND_SAME: + case UpdateService.STATUS_COMPLETE_AND_SAME: schedulePollForUpdates(); break; } } - }); + }; + // TODO: Unregister this properly, not just when successful (see swithc statement above) + LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(pollForUpdatesReceiver); } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapConnecting.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapConnecting.java index 89820fc52..8eb458491 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapConnecting.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapConnecting.java @@ -1,18 +1,23 @@ package org.fdroid.fdroid.views.swap; import android.annotation.TargetApi; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.Build; import android.support.annotation.ColorRes; import android.support.annotation.NonNull; +import android.support.v4.content.LocalBroadcastManager; import android.util.AttributeSet; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; +import android.view.View; +import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; -import org.fdroid.fdroid.ProgressListener; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.localrepo.SwapService; @@ -55,8 +60,7 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity if (peer == null) { Log.e(TAG, "Cannot find the peer to connect to."); - // TODO: Don't go to the selected apps, rather show a Toast message and then - // go to the intro screen. + // TODO: Don't go to the selected apps, rather show a Toast message and then go to the intro screen. getActivity().showSelectApps(); return; } @@ -64,42 +68,68 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity String heading = getContext().getString(R.string.status_connecting_to_repo, peer.getName()); ((TextView) findViewById(R.id.heading)).setText(heading); - UpdateService.UpdateReceiver receiver = getManager().connectTo(peer, peer.shouldPromptForSwapBack()); - - receiver.hideDialog(); - receiver.setListener(new ProgressListener() { + findViewById(R.id.back).setOnClickListener(new OnClickListener() { @Override - public void onProgress(Event event) { - ((TextView) findViewById(R.id.progress)).setText(event.data.getString(UpdateService.EXTRA_ADDRESS)); - boolean finished = false; - boolean error = false; - switch (event.type) { - case UpdateService.EVENT_ERROR: - finished = true; - error = true; - break; - case UpdateService.EVENT_COMPLETE_WITH_CHANGES: - finished = true; - break; - case UpdateService.EVENT_COMPLETE_AND_SAME: - finished = true; - break; - case UpdateService.EVENT_INFO: - break; - } - - if (finished) { - if (error) { - // TODO: Feedback to user about error, suggest fixes. - } else { - getActivity().showSwapConnected(); - } - } - + public void onClick(View v) { + getActivity().showIntro(); } }); + + // TODO: Unregister correctly, not just when being notified of completion or errors. + LocalBroadcastManager.getInstance(getActivity()).registerReceiver(repoUpdateReceiver, new IntentFilter(UpdateService.LOCAL_ACTION_STATUS)); + getManager().connectTo(peer, peer.shouldPromptForSwapBack()); + } + private BroadcastReceiver repoUpdateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + + int statusCode = intent.getIntExtra(UpdateService.EXTRA_STATUS_CODE, -1); + + TextView progressText = ((TextView) findViewById(R.id.progress)); + TextView errorText = ((TextView) findViewById(R.id.error)); + Button backButton = ((Button) findViewById(R.id.back)); + + if (intent.hasExtra(UpdateService.EXTRA_MESSAGE)) { + progressText.setText(intent.getStringExtra(UpdateService.EXTRA_MESSAGE)); + } + + boolean finished = false; + boolean error = false; + + progressText.setVisibility(View.VISIBLE); + errorText.setVisibility(View.GONE); + backButton.setVisibility(View.GONE); + + switch (statusCode) { + case UpdateService.STATUS_ERROR_GLOBAL: + finished = true; + error = true; + break; + case UpdateService.STATUS_COMPLETE_WITH_CHANGES: + finished = true; + break; + case UpdateService.STATUS_COMPLETE_AND_SAME: + finished = true; + break; + case UpdateService.STATUS_INFO: + break; + } + + if (finished) { + LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(repoUpdateReceiver); + if (error) { + progressText.setVisibility(View.GONE); + errorText.setVisibility(View.VISIBLE); + backButton.setVisibility(View.VISIBLE); + } else { + getActivity().showSwapConnected(); + } + } + } + }; + @Override public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) { return true; diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index 263c62a32..1f142dce9 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -294,7 +294,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { inflateInnerView(R.layout.swap_initial_loading); } - private void showIntro() { + public void showIntro() { // If we were previously swapping with a specific client, forget that we were doing that, // as we are starting over now. getService().swapWith(null); diff --git a/F-Droid/test/.classpath b/F-Droid/test/.classpath deleted file mode 100644 index d585386c3..000000000 --- a/F-Droid/test/.classpath +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="src" path="gen"/> - <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> - <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> - <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> - <classpathentry combineaccessrules="false" kind="src" path="/fdroid"/> - <classpathentry kind="output" path="bin/classes"/> -</classpath> diff --git a/F-Droid/test/.project b/F-Droid/test/.project deleted file mode 100644 index 0c2b67ff9..000000000 --- a/F-Droid/test/.project +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>fdroid-test</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.android.ide.eclipse.adt.ApkBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>com.android.ide.eclipse.adt.AndroidNature</nature> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/F-Droid/test/ant.properties b/F-Droid/test/ant.properties deleted file mode 100644 index 99458bdd5..000000000 --- a/F-Droid/test/ant.properties +++ /dev/null @@ -1,19 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked into Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - -tested.project.dir=.. -test.runner=com.zutubi.android.junitreport.JUnitReportTestRunner diff --git a/F-Droid/test/custom_rules.xml b/F-Droid/test/custom_rules.xml deleted file mode 100644 index ee90d3fac..000000000 --- a/F-Droid/test/custom_rules.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project name="test_custom_rules" default="fetch-test-report"> - - <target name="fetch-test-report"> - <xpath - expression="/manifest/@package" - input="${tested.project.dir}/AndroidManifest.xml" - output="tested.package" /> - <echo>Downloading XML test report (/data/data/${tested.package}/files/junit-report.xml)…</echo> - <mkdir dir="junitreports"/> - <exec executable="${adb}" failonerror="true"> - <arg line="${adb.device.arg}"/> - <arg value="pull" /> - <arg value="/data/data/${tested.package}/files/junit-report.xml" /> - <arg value="junit-report.xml" /> - </exec> - </target> - -</project> diff --git a/F-Droid/test/libs/android-junit-report-1.5.8.README b/F-Droid/test/libs/android-junit-report-1.5.8.README deleted file mode 100644 index a89c98533..000000000 --- a/F-Droid/test/libs/android-junit-report-1.5.8.README +++ /dev/null @@ -1,5 +0,0 @@ - -Needed for Jenkins to get JUnit reports. - -* https://github.com/jsankey/android-junit-report -* https://github.com/downloads/jsankey/android-junit-report/android-junit-report-1.5.8.jar diff --git a/F-Droid/test/libs/android-junit-report-1.5.8.jar b/F-Droid/test/libs/android-junit-report-1.5.8.jar deleted file mode 100644 index 09e6a2d4f..000000000 Binary files a/F-Droid/test/libs/android-junit-report-1.5.8.jar and /dev/null differ diff --git a/F-Droid/test/libs/commons-io-2.2.jar b/F-Droid/test/libs/commons-io-2.2.jar deleted file mode 100644 index 84ca56585..000000000 Binary files a/F-Droid/test/libs/commons-io-2.2.jar and /dev/null differ diff --git a/F-Droid/test/libs/commons-io-2.2.jar.README b/F-Droid/test/libs/commons-io-2.2.jar.README deleted file mode 100644 index a330a9794..000000000 --- a/F-Droid/test/libs/commons-io-2.2.jar.README +++ /dev/null @@ -1,5 +0,0 @@ - -Downloaded from: -https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip -https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip.asc -https://archive.apache.org/dist/commons/io/binaries/commons-io-2.2-bin.zip.sha1 diff --git a/F-Droid/test/proguard-project.txt b/F-Droid/test/proguard-project.txt deleted file mode 100644 index f2fe1559a..000000000 --- a/F-Droid/test/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/F-Droid/test/project.properties b/F-Droid/test/project.properties deleted file mode 100644 index e611232d2..000000000 --- a/F-Droid/test/project.properties +++ /dev/null @@ -1,21 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-21 - -# With a target SDK of android-21 (5.0/Lollipop) and a Java 1.7 compiler, you -# can use Java 1.7 features like the <> diamond operator, multi-catch, strings -# in switches, etc. -java.encoding=UTF-8 -java.source=1.7 -java.target=1.7 diff --git a/F-Droid/tools/download-material-icon.sh b/F-Droid/tools/download-material-icon.sh index fc5ce8639..f41b539fd 100755 --- a/F-Droid/tools/download-material-icon.sh +++ b/F-Droid/tools/download-material-icon.sh @@ -15,11 +15,10 @@ function usage { } function download { - REMOTE_DRAWABLE_DIR=$1 - LOCAL_DRAWABLE_DIR=$2 - FILE="ic_${ICON}_48dp.png" - URL="$BASE_URL/$CATEGORY/$REMOTE_DRAWABLE_DIR/$FILE" - DIR="$RES_DIR/$LOCAL_DRAWABLE_DIR" + DRAWABLE_DIR=$1 + FILE="ic_${ICON}_24dp.png" + URL="$BASE_URL/$CATEGORY/$DRAWABLE_DIR/$FILE" + DIR="$RES_DIR/$DRAWABLE_DIR" if [ ! -d $DIR ] then @@ -60,10 +59,9 @@ then exit fi -download drawable-mdpi drawable for SCREEN in $SCREENS do - download "drawable-$SCREEN" "drawable-$SCREEN" + download "drawable-$SCREEN" done echo "" diff --git a/HACKING.md b/HACKING.md index d9aa2ddf3..ee26f8798 100644 --- a/HACKING.md +++ b/HACKING.md @@ -29,10 +29,6 @@ You have three options: * Build with gradle * Build with gradle from source - * Build with ant from source - -Any will work, but if you use gradle, remember that you can use --daemon to -not have to watch gradle load every time. Debugging --------- diff --git a/README.md b/README.md index 1605cd67d..b55254314 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,18 @@ for Android. Building from source with Gradle -------------------------------- -The only required tools are the [Android SDK](http://developer.android.com/sdk/index.html) and Gradle. +The only required tools are the [Android +SDK](http://developer.android.com/sdk/index.html) and Gradle. You should use a relatively new version of Gradle, such as 2.4, or use the gradle wrapper. Once you have checked out the version you wish to build, run: -``` -git submodule update --init -cd F-Droid -gradle clean assembleRelease -``` + cd F-Droid + gradle assembleRelease + +The resulting apk will be in `build/outputs/apk/`. Android Studio -------------- @@ -26,6 +26,13 @@ Android Studio From Android Studio: File -> Import Project -> Select the cloned top folder +Building tips +------------- + +* Use `gradle --daemon` if you are going to build F-Droid multiple times. +* If you get a message like `Could not find com.android.support:support-...`, + make sure that you have the latest Android support maven repository + Direct download --------------- @@ -65,8 +72,42 @@ command line: This will build and install F-Droid and the test apk, then execute the entire test suite on the device or emulator. -See the [Android Gradle user guide](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing) for more details, including how to use Android Studio to run tests (which provides -more useful feedback than the command line). +See the [Android Gradle user +guide](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing) +for more details, including how to use Android Studio to run tests (which +provides more useful feedback than the command line). + + +Versioning +---------- + +Each stable version follows the `X.Y` pattern. Hotfix releases - i.e. when a +stable has an important bug that needs immediate fixing - will follow the +`X.Y.Z` pattern. + +Before each stable release, a number of alpha releases will be released. They +will follow the pattern `X.Y-alphaN`, where `N` is the current alpha number. +These will usually include changes and new features that have not been tested +enough for a stable release, so use at your own risk. Testers and reporters +are very welcome. + +The version codes use a number of digits per each of these keys: `XYYZNN`. +So for example, 1.3.1 would be `103150` and 0.95-alpha13 would be `95013` +(leading zeros are omitted). + +Note that we use a trailing `50` for actual stable releases, so alphas are +limited to `-alpha49`. + +This is an example of a release process for release **0.95**: + +* We are currently at stable **0.94** +* **0.95-alpha1** is released +* **0.95-alpha2** is released +* **0.95-alpha3** is released +* Testing process (1-2 weeks) during which no new features are merged in +* **0.95** is released +* A bug is reported on the stable release and fixed +* **0.95.1** is released License diff --git a/build.gradle b/build.gradle index 20ee7f325..519664ef3 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,6 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.2' + classpath 'com.android.tools.build:gradle:1.3.0' } } diff --git a/extern/Support b/extern/Support deleted file mode 160000 index e4ecf4ad3..000000000 --- a/extern/Support +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4ecf4ad3dd5a1c229e30db56a224eacc72a7fd2 diff --git a/jenkins-build b/jenkins-build index ab5ffe4f8..f4fbdaf57 100755 --- a/jenkins-build +++ b/jenkins-build @@ -1,7 +1,7 @@ #!/bin/sh # -# Jenkins uses this script to set up the ant build. Jenkins will then call -# ant itself once this script has completed. +# Jenkins uses this script to set up the gradle build. Jenkins will then call +# gradle itself once this script has completed. set -e set -x @@ -15,7 +15,6 @@ sed -i \ -e "s,android:versionName=\"\([^\"][^\"]*\)\",android:versionName=\"\1.$versionNameDate\"," \ F-Droid/AndroidManifest.xml - if [ -z $ANDROID_HOME ]; then if [ -e ~/.android/bashrc ]; then . ~/.android/bashrc @@ -26,4 +25,3 @@ if [ -z $ANDROID_HOME ]; then fi cd F-Droid -./ant-prepare.sh