├── .github ├── ISSUE_TEMPLATE │ └── 01_bug_report.yml └── workflows │ └── android.yml ├── .gitignore ├── .kotlin └── sessions │ └── kotlin-compiler-13018979230585017163.salive ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── github │ └── res │ │ └── xml │ │ └── accessibility_service.xml │ ├── google │ └── res │ │ └── xml │ │ └── placeholder_service.xml │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── com │ │ └── eightbit │ │ │ ├── app │ │ │ └── CoverOptions.kt │ │ │ ├── content │ │ │ └── ScaledContext.kt │ │ │ ├── io │ │ │ └── Debug.kt │ │ │ ├── material │ │ │ └── IconifiedSnackbar.kt │ │ │ ├── net │ │ │ └── JSONExecutor.kt │ │ │ ├── os │ │ │ └── Version.kt │ │ │ ├── pm │ │ │ └── PackageRetriever.kt │ │ │ ├── samsprung │ │ │ ├── AccessibilityObserver.kt │ │ │ ├── LayoutStateChangeCallback.kt │ │ │ ├── NotificationReceiver.kt │ │ │ ├── OnBroadcastService.kt │ │ │ ├── SamSprung.kt │ │ │ ├── SamSprungOverlay.kt │ │ │ ├── drawer │ │ │ │ ├── AppDisplayListener.kt │ │ │ │ ├── AppDrawerFragment.kt │ │ │ │ ├── CoverStateAdapter.kt │ │ │ │ ├── DrawerAppAdapter.kt │ │ │ │ ├── LauncherManager.kt │ │ │ │ ├── NotificationAdapter.kt │ │ │ │ ├── NotificationFragment.kt │ │ │ │ ├── OrientationManager.kt │ │ │ │ ├── PanelViewFragment.kt │ │ │ │ ├── PanelWidgetManager.kt │ │ │ │ └── panels │ │ │ │ │ ├── DesktopBinder.kt │ │ │ │ │ ├── PanelWidgetInfo.kt │ │ │ │ │ ├── WidgetHost.kt │ │ │ │ │ ├── WidgetHostView.kt │ │ │ │ │ ├── WidgetInfo.kt │ │ │ │ │ ├── WidgetModel.kt │ │ │ │ │ ├── WidgetPreviews.kt │ │ │ │ │ ├── WidgetProvider.java │ │ │ │ │ └── WidgetSettings.kt │ │ │ ├── settings │ │ │ │ ├── CoverPreferences.kt │ │ │ │ ├── DonationManager.kt │ │ │ │ ├── FilteredAppsAdapter.kt │ │ │ │ └── Preferences.kt │ │ │ ├── speech │ │ │ │ └── VoiceRecognizer.kt │ │ │ └── update │ │ │ │ ├── UpdateManager.kt │ │ │ │ ├── UpdateReceiver.kt │ │ │ │ └── UpdateShimActivity.kt │ │ │ ├── view │ │ │ ├── AnimatedLinearLayout.kt │ │ │ └── OnSwipeTouchListener.kt │ │ │ ├── viewpager │ │ │ ├── CardFlipTransformer.kt │ │ │ ├── ClockSpinTransformer.kt │ │ │ ├── DepthTransformer.kt │ │ │ ├── FidgetSpinTransformer.kt │ │ │ ├── PopTransformer.kt │ │ │ ├── SpinnerTransformer.kt │ │ │ └── TossTransformer.kt │ │ │ └── widget │ │ │ ├── NestedScrollableHost.kt │ │ │ └── RecyclerViewTouch.kt │ └── eightbitlab │ │ └── com │ │ └── blurview │ │ ├── BlurAlgorithm.kt │ │ ├── BlurController.kt │ │ ├── BlurView.kt │ │ ├── BlurViewCanvas.kt │ │ ├── BlurViewFacade.kt │ │ ├── NoOpController.kt │ │ ├── PreDrawBlurController.kt │ │ ├── RenderEffectBlur.kt │ │ ├── RenderScriptBlur.kt │ │ └── SizeScaler.kt │ └── res │ ├── color │ ├── primary_text_dark.xml │ └── primary_text_light.xml │ ├── drawable-night-v21 │ └── button_rippled.xml │ ├── drawable-night │ ├── ic_bluetooth_off_24dp.xml │ ├── ic_bluetooth_on_24dp.xml │ ├── ic_cancel_presentation_24dp.xml │ ├── ic_delete_forever_24dp.xml │ ├── ic_do_not_disturb_off_24dp.xml │ ├── ic_do_not_disturb_on_24dp.xml │ ├── ic_expand_20dp.xml │ ├── ic_fingerprint_24dp.xml │ ├── ic_flashlight_off_24dp.xml │ ├── ic_flashlight_on_24dp.xml │ ├── ic_github_octocat_24dp.xml │ ├── ic_insert_page_break_24dp.xml │ ├── ic_keyboard_24dp.xml │ ├── ic_launch_24dp.xml │ ├── ic_menu_24.xml │ ├── ic_move_up_20dp.xml │ ├── ic_nfc_off_24dp.xml │ ├── ic_nfc_on_24dp.xml │ ├── ic_record_voice_over_24dp.xml │ ├── ic_samsprung_24dp.xml │ ├── ic_screen_lock_rotation_24.xml │ ├── ic_screen_rotation_24.xml │ ├── ic_send_24dp.xml │ ├── ic_software_update_24.xml │ ├── ic_sound_off_24dp.xml │ ├── ic_sound_on_24dp.xml │ ├── ic_support_required_24dp.xml │ ├── ic_swipe_down_24dp.xml │ ├── ic_voice_over_off_24dp.xml │ ├── ic_wallpaper_24dp.xml │ ├── ic_widgets_24dp.xml │ ├── ic_wifi_off_24dp.xml │ ├── ic_wifi_on_24dp.xml │ ├── rounded_layout.xml │ └── rounded_layout_themed.xml │ ├── drawable-v21 │ └── button_rippled.xml │ ├── drawable │ ├── bg_appwidget_error.9.png │ ├── card_foreground.xml │ ├── card_foreground_selector.xml │ ├── ic_arrow_back_24dp.xml │ ├── ic_bluetooth_off_24dp.xml │ ├── ic_bluetooth_on_24dp.xml │ ├── ic_cancel_presentation_24dp.xml │ ├── ic_delete_forever_24dp.xml │ ├── ic_do_not_disturb_off_24dp.xml │ ├── ic_do_not_disturb_on_24dp.xml │ ├── ic_expand_20dp.xml │ ├── ic_fingerprint_24dp.xml │ ├── ic_flashlight_off_24dp.xml │ ├── ic_flashlight_on_24dp.xml │ ├── ic_github_octocat_24dp.xml │ ├── ic_github_sponsor_24dp.xml │ ├── ic_google_play_24dp.xml │ ├── ic_home_24dp.xml │ ├── ic_insert_page_break_24dp.xml │ ├── ic_keyboard_24dp.xml │ ├── ic_launch_24dp.xml │ ├── ic_launcher_background.png │ ├── ic_launcher_foreground.png │ ├── ic_menu_24.xml │ ├── ic_move_up_20dp.xml │ ├── ic_nfc_off_24dp.xml │ ├── ic_nfc_on_24dp.xml │ ├── ic_paypal_donation.xml │ ├── ic_record_voice_over_24dp.xml │ ├── ic_samsprung_24dp.xml │ ├── ic_screen_lock_rotation_24.xml │ ├── ic_screen_rotation_24.xml │ ├── ic_send_24dp.xml │ ├── ic_settings_24dp.xml │ ├── ic_software_update_24.xml │ ├── ic_sound_off_24dp.xml │ ├── ic_sound_on_24dp.xml │ ├── ic_support_required_24dp.xml │ ├── ic_swipe_down_24dp.xml │ ├── ic_voice_over_off_24dp.xml │ ├── ic_wallpaper_24dp.xml │ ├── ic_widget_preview.png │ ├── ic_widgets_24dp.xml │ ├── ic_wifi_off_24dp.xml │ ├── ic_wifi_on_24dp.xml │ ├── notification_badge.xml │ ├── rounded_layout.xml │ ├── rounded_layout_themed.xml │ └── widget_preview_tile.png │ ├── layout │ ├── appwidget_error.xml │ ├── button_cancel_sub.xml │ ├── button_paypal.xml │ ├── button_sponsor.xml │ ├── color_panel.xml │ ├── configure_switch.xml │ ├── donation_layout.xml │ ├── drawer_apps_card.xml │ ├── drawer_apps_icon.xml │ ├── dropdown_item_1.xml │ ├── filtered_apps_item.xml │ ├── fingerprint_auth.xml │ ├── fragment_drawer.xml │ ├── fragment_notices.xml │ ├── fragment_panel.xml │ ├── home_main_view.xml │ ├── navigation_menu.xml │ ├── notification_card.xml │ ├── notification_reply.xml │ ├── panel_picker_view.xml │ ├── preferences_layout.xml │ ├── prefs_drawer.xml │ ├── prefs_general.xml │ ├── prefs_permissions.xml │ ├── social_menu_bar.xml │ ├── system_menu.xml │ ├── toggle_state_icon.xml │ ├── toolbar_options.xml │ └── widget_preview.xml │ ├── menu │ ├── cover_quick_toggles.xml │ └── cover_settings_menu.xml │ ├── mipmap-anydpi-v26 │ ├── sprung_icon.xml │ └── sprung_icon_round.xml │ ├── mipmap-hdpi │ ├── sprung_icon.png │ ├── sprung_icon_background.png │ ├── sprung_icon_foreground.png │ └── sprung_icon_round.png │ ├── mipmap-mdpi │ ├── sprung_icon.png │ ├── sprung_icon_background.png │ ├── sprung_icon_foreground.png │ └── sprung_icon_round.png │ ├── mipmap-xhdpi │ ├── sprung_icon.png │ ├── sprung_icon_background.png │ ├── sprung_icon_foreground.png │ └── sprung_icon_round.png │ ├── mipmap-xxhdpi │ ├── sprung_icon.png │ ├── sprung_icon_background.png │ ├── sprung_icon_foreground.png │ └── sprung_icon_round.png │ ├── mipmap-xxxhdpi │ ├── sprung_icon.png │ ├── sprung_icon_background.png │ ├── sprung_icon_foreground.png │ └── sprung_icon_round.png │ ├── raw │ └── display_settings.xml │ ├── values-de │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-it │ └── strings.xml │ ├── values-ko │ └── strings.xml │ ├── values-night │ ├── colors.xml │ └── themes.xml │ ├── values-pl │ └── strings.xml │ ├── values │ ├── accessibility.xml │ ├── arrays.xml │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── donottranslate.xml │ ├── strings.xml │ ├── styles.xml │ └── themes.xml │ └── xml │ ├── extraction_content.xml │ ├── file_provider_paths.xml │ └── full_backup_content.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/ISSUE_TEMPLATE/01_bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Report a Problem 2 | description: File a bug report 3 | title: "[Issue]: " 4 | labels: ["Entomology"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Please provide as much detail as possible 10 | - type: textarea 11 | id: what-happened 12 | attributes: 13 | label: Issue Description 14 | description: Please describe the issue in your own words 15 | placeholder: This is how you would see the problem again 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: logcat 20 | attributes: 21 | label: Logcat Output 22 | description: Long press inside this box and select "Paste" 23 | placeholder: This is a logcat, not a secondary description 24 | render: shell 25 | validations: 26 | required: true 27 | - type: checkboxes 28 | id: requirements 29 | attributes: 30 | label: Guide Confirmation 31 | description: By submitting this issue, you confirm checking the [guide](https://samsprung.github.io/launcher/index.html) for SamSprung TooUI 32 | options: 33 | - label: I have reviewed the guide and included valid logcat content 34 | required: true 35 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ launcher ] 6 | 7 | permissions: 8 | contents: read 9 | actions: write 10 | 11 | jobs: 12 | clean: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 2 15 | 16 | steps: 17 | - name: Remove artifacts 18 | continue-on-error: true 19 | uses: c-hive/gha-remove-artifacts@v1.3.0 20 | with: 21 | age: '2 days' # ' ', parsed by Moment.js 22 | 23 | - name: Purge cache 24 | continue-on-error: true 25 | uses: MyAlbum/purge-cache@v1 26 | with: 27 | max-age: 172800 # 2 days, default: 7 days since last use 28 | 29 | build: 30 | runs-on: ubuntu-latest 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | with: 35 | submodules: recursive 36 | - name: set up JDK 17 37 | uses: actions/setup-java@v4 38 | with: 39 | java-version: '17' 40 | distribution: 'temurin' 41 | cache: gradle 42 | 43 | - name: Grant execute permission for gradlew 44 | run: chmod +x gradlew 45 | - name: Build with Gradle 46 | run: ./gradlew assembleGithubRelease 47 | 48 | - uses: r0adkll/sign-android-release@v1 49 | name: Sign app APK 50 | # ID used to access action output 51 | id: sign_app 52 | with: 53 | releaseDirectory: app/build/outputs/apk/github/release 54 | signingKeyBase64: ${{ secrets.KEYSTORE }} 55 | alias: ${{ secrets.KEY_ALIAS }} 56 | keyStorePassword: ${{ secrets.STOREPASS }} 57 | keyPassword: ${{ secrets.KEYPASS }} 58 | env: 59 | # override default build-tools version (29.0.3) -- optional 60 | BUILD_TOOLS_VERSION: "34.0.0" 61 | 62 | - name: Retrieve commit identification 63 | run: | 64 | GIT_BRANCH=$(git name-rev --name-only HEAD) 65 | echo "GIT_BRANCH=${GIT_BRANCH}" >> $GITHUB_ENV 66 | GIT_HASH=$(git rev-parse --short HEAD) 67 | echo "GIT_HASH=${GIT_HASH}" >> $GITHUB_ENV 68 | 69 | - uses: actions/upload-artifact@v4 70 | with: 71 | name: SamSprung-${{ env.GIT_HASH }} 72 | retention-days: 1 73 | path: ${{steps.sign_app.outputs.signedReleaseFile}} 74 | 75 | - uses: SamSprung/action-github-releases@v1.0.0 76 | if: ${{ github.event_name != 'pull_request' }} 77 | with: 78 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 79 | automatic_release_tag: "sideload" 80 | prerelease: ${{ env.GIT_BRANCH != 'launcher' }} 81 | title: SamSprung-${{ env.GIT_HASH }} 82 | files: ${{steps.sign_app.outputs.signedReleaseFile}} 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.orig 3 | 4 | local.properties 5 | keystore.properties 6 | *.iml 7 | 8 | .cxx 9 | .externalNativeBuild 10 | .gradle 11 | .idea 12 | 13 | captures 14 | build 15 | release 16 | -------------------------------------------------------------------------------- /.kotlin/sessions/kotlin-compiler-13018979230585017163.salive: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/.kotlin/sessions/kotlin-compiler-13018979230585017163.salive -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2012-2024 AbandonedCart. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * For the purpose of this license, the phrase "GitHub labels" shall be 10 | * used to refer to "AbandonedCart", "TwistedUmbrella", "SamSprung", 11 | * and "TagMo" such that these entities are collectively considered the 12 | * equivalent of any usage of the aforementioned phrase. 13 | * 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 17 | * 2. Redistributions in binary form must reproduce the above copyright 18 | * notice, this list of conditions and the following disclaimer in 19 | * the documentation and/or other materials provided with the 20 | * distribution. 21 | * 22 | * 3. All materials mentioning features or use of this software and 23 | * redistributions of any form whatsoever must display the following 24 | * acknowledgment unless made available by tagged, public "commits": 25 | * "This product includes software developed by AbandonedCart" 26 | * 27 | * 4. The GitHub labels must not be used in any form to endorse or promote 28 | * products derived from this software without prior written permission. 29 | * For written permission, please contact enderinexiledc@gmail.com 30 | * 31 | * 5. Products derived from this software may not be called by the GitHub 32 | * labels nor may these labels appear in their names or product details 33 | * without prior written permission of AbandonedCart. 34 | * 35 | * THIS SOFTWARE IS PROVIDED BY AbandonedCart ``AS IS'' AND ANY 36 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 | * OF THE POSSIBILITY OF SUCH DAMAGE. 47 | * ==================================================================== 48 | * 49 | * The license and distribution terms for any publicly available version or 50 | * derivative of this code cannot be changed. i.e. this code cannot simply be 51 | * copied and put under another distribution license 52 | * [including the GNU Public License.] Content not subject to these terms is 53 | * subject to to the terms and conditions of the Apache License, Version 2.0. 54 | */ 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |

SamSprung TooUI Manual (Guides)

3 |

4 | 5 |

6 | Get it on Google Play 7 |

8 | 9 |

10 | 11 |



12 | 13 | ![SamSprung Logo](https://github.com/SamSprung/.github/raw/main/assets/feature_graphic.png) 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | -dontobfuscate 9 | -optimizations !code/allocation/variable 10 | 11 | # If your project uses WebView with JS, uncomment the following 12 | # and specify the fully qualified class name to the JavaScript interface 13 | # class: 14 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 15 | # public *; 16 | #} 17 | 18 | # Uncomment this to preserve the line number information for 19 | # debugging stack traces. 20 | -keepattributes *Annotation*,SourceFile,LineNumberTable 21 | 22 | # If you keep the line number information, uncomment this to 23 | # hide the original source file name. 24 | #-renamesourcefileattribute SourceFile 25 | 26 | -keep class com.google.android.material.R$drawable { *; } -------------------------------------------------------------------------------- /app/src/github/res/xml/accessibility_service.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/google/res/xml/placeholder_service.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/app/CoverOptions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.app 16 | 17 | import android.app.ActivityOptions 18 | import android.content.Intent 19 | import android.graphics.Rect 20 | import android.view.View 21 | import androidx.core.app.ActivityOptionsCompat 22 | 23 | class CoverOptions(private var bounds: Rect?) { 24 | 25 | fun getActivityOptions(display: Int): ActivityOptions { 26 | return ActivityOptions.makeBasic().setLaunchDisplayId(display).setLaunchBounds(bounds) 27 | } 28 | 29 | fun getAnimatedOptions(display: Int, anchor: View?, intent: Intent?): ActivityOptions { 30 | return intent?.sourceBounds?.let { bounds -> 31 | ActivityOptions.makeScaleUpAnimation( 32 | anchor, 33 | bounds.left, 34 | bounds.top, 35 | bounds.width(), 36 | bounds.height() 37 | ).setLaunchDisplayId(display).setLaunchBounds(bounds) 38 | } ?: getActivityOptions(display) 39 | } 40 | 41 | fun getActivityOptionsCompat(display: Int): ActivityOptionsCompat { 42 | return ActivityOptionsCompat.makeBasic().setLaunchDisplayId(display).setLaunchBounds(bounds) 43 | } 44 | 45 | fun getAnimatedOptionsCompat(display: Int, anchor: View, intent: Intent?): ActivityOptionsCompat { 46 | return intent?.sourceBounds?.let { bounds -> 47 | ActivityOptionsCompat.makeScaleUpAnimation( 48 | anchor, 49 | bounds.left, 50 | bounds.top, 51 | bounds.width(), 52 | bounds.height() 53 | ).setLaunchDisplayId(display).setLaunchBounds(bounds) 54 | } ?: getActivityOptionsCompat(display) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/os/Version.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2023 AbandonedCart. All rights reserved. 4 | * 5 | * https://github.com/AbandonedCart/AbandonedCart/blob/main/LICENSE#L4 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.os 16 | 17 | import android.os.Build 18 | 19 | object Version { 20 | 21 | /** 22 | * Android 12, API 31 23 | */ 24 | @JvmStatic 25 | val isSnowCone: Boolean get() { 26 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S 27 | } 28 | 29 | /** 30 | * Android 13, API 33 31 | */ 32 | @JvmStatic 33 | val isTiramisu: Boolean get() { 34 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU 35 | } 36 | 37 | /** 38 | * Android 14, API 34 39 | */ 40 | @JvmStatic 41 | val isUpsideDownCake: Boolean get() { 42 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/AccessibilityObserver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung 16 | 17 | import android.accessibilityservice.AccessibilityService 18 | import android.accessibilityservice.AccessibilityServiceInfo 19 | import android.content.Context 20 | import android.content.Intent 21 | import android.provider.Settings 22 | import android.view.WindowManager 23 | import android.view.accessibility.AccessibilityEvent 24 | import java.io.File 25 | 26 | class AccessibilityObserver : AccessibilityService() { 27 | 28 | companion object { 29 | private lateinit var observerInstance: AccessibilityObserver 30 | private var isConnected: Boolean = false 31 | fun getInstance() : AccessibilityObserver? { 32 | return if (isConnected) observerInstance else null 33 | } 34 | fun hasEnabledService(context: Context): Boolean { 35 | if (BuildConfig.GOOGLE_PLAY) return false 36 | val serviceString = Settings.Secure.getString(context.contentResolver, 37 | Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES 38 | ) 39 | return serviceString?.contains(context.packageName 40 | + File.separator + AccessibilityObserver::class.java.name) == true 41 | } 42 | fun performBackAction() { 43 | getInstance()?.performGlobalAction(GLOBAL_ACTION_BACK) 44 | } 45 | 46 | fun getWindowManager() : WindowManager { 47 | return getInstance()?.getSystemService(WINDOW_SERVICE) as WindowManager 48 | } 49 | } 50 | 51 | init { 52 | observerInstance = this 53 | } 54 | 55 | override fun onServiceConnected() { 56 | val info = AccessibilityServiceInfo() 57 | info.packageNames = arrayOf(packageName) 58 | info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED 59 | info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC 60 | info.notificationTimeout = 100 61 | serviceInfo = info 62 | isConnected = true 63 | } 64 | 65 | override fun onAccessibilityEvent(event: AccessibilityEvent) { } 66 | 67 | override fun onInterrupt() { 68 | if (null == getInstance()) observerInstance = this 69 | } 70 | 71 | override fun onUnbind(intent: Intent?): Boolean { 72 | isConnected = false 73 | return super.onUnbind(intent) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/LayoutStateChangeCallback.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.samsprung 2 | 3 | import androidx.core.util.Consumer 4 | import androidx.window.layout.FoldingFeature 5 | import androidx.window.layout.WindowLayoutInfo 6 | 7 | class LayoutStateChangeCallback : Consumer { 8 | 9 | interface FoldingFeatureListener { 10 | fun onHalfOpened() 11 | fun onSeparating() 12 | fun onFlat() 13 | fun onNormal() 14 | } 15 | 16 | private var listener: FoldingFeatureListener? = null 17 | 18 | fun setListener(listener: FoldingFeatureListener) { 19 | this.listener = listener 20 | } 21 | 22 | override fun accept(newLayoutInfo: WindowLayoutInfo) { 23 | for (feature in newLayoutInfo.displayFeatures) { 24 | if (feature is FoldingFeature) { 25 | when (feature.state) { 26 | FoldingFeature.State.HALF_OPENED -> { 27 | listener?.onHalfOpened() 28 | } 29 | FoldingFeature.State.FLAT -> { 30 | if (feature.isSeparating) { 31 | listener?.onSeparating() 32 | } else { 33 | listener?.onFlat() 34 | } 35 | } 36 | else -> { 37 | listener?.onNormal() 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/SamSprung.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung 16 | 17 | import android.app.Application 18 | import android.app.KeyguardManager 19 | import androidx.appcompat.app.AppCompatDelegate 20 | import com.eightbit.io.Debug 21 | import com.eightbit.samsprung.drawer.OrientationManager 22 | import com.eightbit.samsprung.settings.Preferences 23 | import java.io.PrintWriter 24 | import java.io.StringWriter 25 | import kotlin.system.exitProcess 26 | 27 | const val organization = "SamSprung" 28 | 29 | class SamSprung : Application() { 30 | 31 | fun setThemePreference() { 32 | when (getSharedPreferences(Preferences.prefsValue, MODE_PRIVATE).getInt(Preferences.prefThemes, 0)) { 33 | 0 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) 34 | 1 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 35 | 2 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) 36 | } 37 | } 38 | 39 | companion object { 40 | const val provider: String = "${BuildConfig.APPLICATION_ID}.provider" 41 | const val updating: String = "${BuildConfig.APPLICATION_ID}.UPDATING" 42 | const val services: String = "${BuildConfig.APPLICATION_ID}.SERVICES" 43 | const val launcher: String = "${BuildConfig.APPLICATION_ID}.LAUNCHER" 44 | 45 | const val request_code = 8675309 46 | const val notification = request_code.toString() 47 | 48 | var hasSubscription = false 49 | 50 | private const val commitHash = "#${BuildConfig.COMMIT}" 51 | val versionLabel = "$organization ${BuildConfig.VERSION_NAME} (${ 52 | if (BuildConfig.GOOGLE_PLAY) "Play" else "GitHub" 53 | } ${ 54 | if (BuildConfig.BUILD_TYPE == "release") "Release" else "Debug" 55 | }) $commitHash" 56 | } 57 | 58 | override fun onCreate() { 59 | super.onCreate() 60 | AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) 61 | 62 | Thread.setDefaultUncaughtExceptionHandler { _: Thread?, error: Throwable -> 63 | val exception = StringWriter() 64 | error.printStackTrace(PrintWriter(exception)) 65 | try { 66 | OrientationManager(this).removeOrientationLayout() 67 | } catch (_: Exception) { } 68 | try { 69 | Debug(this).processException( 70 | with (getSystemService(KEYGUARD_SERVICE) as KeyguardManager) { isDeviceSecure }, 71 | exception.toString() 72 | ) 73 | } catch (_: Exception) { } 74 | // Unrecoverable error encountered 75 | android.os.Process.killProcess(android.os.Process.myPid()) 76 | exitProcess(-1) 77 | } 78 | 79 | setThemePreference() 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/CoverStateAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung.drawer 16 | 17 | import androidx.appcompat.app.AppCompatActivity 18 | import androidx.fragment.app.Fragment 19 | import androidx.viewpager2.adapter.FragmentStateAdapter 20 | 21 | class CoverStateAdapter(fragmentActivity: AppCompatActivity) : FragmentStateAdapter(fragmentActivity) { 22 | private val mFragments: ArrayList = arrayListOf() 23 | private val mFragmentIDs: ArrayList = arrayListOf() 24 | private val noticeList = NotificationFragment() 25 | private val appDrawer = AppDrawerFragment() 26 | 27 | fun addFragment() : Int { 28 | val fragment = PanelViewFragment() 29 | val position = mFragmentIDs.size + 2 30 | mFragments.add(fragment) 31 | notifyItemInserted(position) 32 | mFragmentIDs.add(position) 33 | return position 34 | } 35 | 36 | fun removeFragment(fragmentID: Int) { 37 | val position = fragmentID - 2 38 | mFragments.removeAt(position) 39 | mFragmentIDs.removeAt(position) 40 | mFragments.trimToSize() 41 | mFragmentIDs.trimToSize() 42 | notifyItemRemoved(fragmentID) 43 | } 44 | 45 | fun getFragment(fragmentID: Int) : PanelViewFragment { 46 | return mFragments[fragmentID - 2] 47 | } 48 | 49 | override fun createFragment(position: Int): Fragment { 50 | return when (position) { 51 | 0 -> noticeList 52 | 1 -> appDrawer 53 | else -> mFragments[position - 2] 54 | } 55 | } 56 | 57 | override fun getItemId(position: Int): Long { 58 | return if (position < 2) position.toLong() else mFragmentIDs[position - 2].toLong() 59 | } 60 | 61 | override fun getItemCount(): Int { 62 | return mFragmentIDs.size + 2 63 | } 64 | 65 | override fun containsItem(itemId: Long): Boolean { 66 | return mFragmentIDs.contains(itemId.toInt()) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/OrientationManager.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.samsprung.drawer 2 | 3 | import android.content.Context 4 | import android.content.pm.ActivityInfo 5 | import android.graphics.PixelFormat 6 | import android.view.View 7 | import android.view.WindowManager 8 | import android.widget.LinearLayout 9 | import java.lang.ref.SoftReference 10 | 11 | class OrientationManager(context: Context) { 12 | 13 | private val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager 14 | private val orientationManager = LinearLayout(context) 15 | 16 | private val orientationLayout = WindowManager.LayoutParams( 17 | WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 18 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or 19 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 20 | PixelFormat.TRANSPARENT 21 | ) 22 | 23 | companion object { 24 | private var orientationView: SoftReference? = null 25 | } 26 | 27 | fun addOrientationLayout(orientation: Int) { 28 | orientationLayout.screenOrientation = orientation 29 | windowManager.addView(orientationManager, orientationLayout) 30 | orientationManager.visibility = View.VISIBLE 31 | orientationView = SoftReference(orientationManager) 32 | } 33 | 34 | fun removeOrientationLayout() { 35 | try { 36 | orientationView?.let { 37 | orientationLayout.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 38 | windowManager.updateViewLayout(it.get(), orientationLayout) 39 | try { 40 | windowManager.removeViewImmediate(it.get()) 41 | } catch (_: Exception) { 42 | try { windowManager.removeView(it.get()) } catch (_: Exception) { } 43 | } 44 | } ?: windowManager.run { 45 | orientationLayout.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 46 | updateViewLayout(orientationManager, orientationLayout) 47 | try { 48 | removeViewImmediate(orientationManager) 49 | } catch (_: Exception) { 50 | try { 51 | removeView(orientationManager) 52 | } catch (_: Exception) { } 53 | } 54 | } 55 | } catch (_: Exception) { } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/PanelViewFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung.drawer 16 | 17 | import android.os.Bundle 18 | import android.view.LayoutInflater 19 | import android.view.View 20 | import android.view.ViewGroup 21 | import android.widget.LinearLayout 22 | import androidx.fragment.app.Fragment 23 | import com.eightbit.samsprung.R 24 | 25 | class PanelViewFragment : Fragment() { 26 | 27 | private var listener: ViewCreatedListener? = null 28 | 29 | fun setListener(listener: ViewCreatedListener) { 30 | this.listener = listener 31 | } 32 | 33 | fun getLayout() : LinearLayout { 34 | return requireView() as LinearLayout 35 | } 36 | 37 | override fun onCreateView( 38 | inflater: LayoutInflater, container: ViewGroup?, 39 | savedInstanceState: Bundle? 40 | ): View { 41 | return inflater.inflate(R.layout.fragment_panel, container, false) 42 | } 43 | 44 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 45 | super.onViewCreated(view, savedInstanceState) 46 | listener?.onViewCreated(view) 47 | } 48 | 49 | interface ViewCreatedListener { 50 | fun onViewCreated(view: View) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/panels/DesktopBinder.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.samsprung.drawer.panels 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import android.os.Message 6 | import android.os.MessageQueue 7 | import com.eightbit.samsprung.SamSprungOverlay 8 | import java.lang.ref.SoftReference 9 | import java.util.LinkedList 10 | 11 | class DesktopBinder( 12 | launcher: SamSprungOverlay, shortcuts: ArrayList?, 13 | appWidgets: ArrayList? 14 | ) : Handler(Looper.getMainLooper()), MessageQueue.IdleHandler { 15 | private val mShortcuts: ArrayList? = shortcuts 16 | private val mAppWidgets: LinkedList 17 | private val mLauncher: SoftReference = SoftReference(launcher) 18 | var mTerminate = false 19 | fun startBindingItems() { 20 | obtainMessage(MESSAGE_BIND_ITEMS, 0, mShortcuts!!.size).sendToTarget() 21 | } 22 | 23 | fun startBindingAppWidgetsWhenIdle() { 24 | // Ask for notification when message queue becomes idle 25 | val messageQueue = Looper.myQueue() 26 | messageQueue.addIdleHandler(this) 27 | } 28 | 29 | override fun queueIdle(): Boolean { 30 | // Queue is idle, so start binding items 31 | startBindingAppWidgets() 32 | return false 33 | } 34 | 35 | private fun startBindingAppWidgets() { 36 | obtainMessage(MESSAGE_BIND_APPWIDGETS).sendToTarget() 37 | } 38 | 39 | override fun handleMessage(msg: Message) { 40 | val launcher = mLauncher.get() 41 | if (launcher == null || mTerminate) { 42 | return 43 | } 44 | when (msg.what) { 45 | MESSAGE_BIND_ITEMS -> { 46 | launcher.bindItems(this, mShortcuts, msg.arg1, msg.arg2) 47 | } 48 | MESSAGE_BIND_APPWIDGETS -> { 49 | launcher.bindAppWidgets(this, mAppWidgets) 50 | } 51 | } 52 | } 53 | 54 | companion object { 55 | const val MESSAGE_BIND_ITEMS = 0x1 56 | const val MESSAGE_BIND_APPWIDGETS = 0x2 57 | 58 | // Number of items to bind in every pass 59 | const val ITEMS_COUNT = 6 60 | } 61 | 62 | init { 63 | // Sort widgets so active workspace is bound first 64 | val size = appWidgets!!.size 65 | mAppWidgets = LinkedList() 66 | for (i in 0 until size) { 67 | val appWidgetInfo = appWidgets[i] 68 | // if (appWidgetInfo.screen == 0) { 69 | // mAppWidgets.addFirst(appWidgetInfo) 70 | // } else { 71 | mAppWidgets.addLast(appWidgetInfo) 72 | // } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/panels/PanelWidgetInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.eightbit.samsprung.drawer.panels 18 | 19 | import android.appwidget.AppWidgetHostView 20 | import android.content.ContentValues 21 | import com.eightbit.samsprung.drawer.panels.WidgetSettings.Favorites 22 | 23 | /** 24 | * Represents a widget, which just contains an identifier. 25 | */ 26 | class PanelWidgetInfo(appWidgetId: Int) : WidgetInfo() { 27 | /** 28 | * Identifier for this widget when talking with [android.appwidget.AppWidgetManager] for updates. 29 | */ 30 | var appWidgetId: Int 31 | 32 | /** 33 | * View that holds this widget after it's been created. This view isn't created 34 | * until Launcher knows it's needed. 35 | */ 36 | var hostView: AppWidgetHostView? = null 37 | override fun onAddToDatabase(values: ContentValues) { 38 | super.onAddToDatabase(values) 39 | values.put(Favorites.APPWIDGET_ID, appWidgetId) 40 | } 41 | 42 | override fun toString(): String { 43 | return appWidgetId.toString() 44 | } 45 | 46 | init { 47 | itemType = Favorites.ITEM_TYPE_APPWIDGET 48 | this.appWidgetId = appWidgetId 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/panels/WidgetHost.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.eightbit.samsprung.drawer.panels 18 | 19 | import android.appwidget.AppWidgetHost 20 | import android.appwidget.AppWidgetHostView 21 | import android.appwidget.AppWidgetProviderInfo 22 | import android.content.Context 23 | 24 | /** 25 | * Specific [AppWidgetHost] that creates our [WidgetHostView] 26 | * which correctly captures all long-press events. This ensures that users can 27 | * always pick up and move widgets. 28 | */ 29 | class WidgetHost(context: Context?, hostId: Int) : AppWidgetHost(context, hostId) { 30 | override fun onCreateView( 31 | context: Context, appWidgetId: Int, appWidget: AppWidgetProviderInfo? 32 | ): AppWidgetHostView { 33 | return WidgetHostView(context) 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/panels/WidgetHostView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.eightbit.samsprung.drawer.panels 18 | 19 | import android.appwidget.AppWidgetHostView 20 | import android.content.Context 21 | import android.view.LayoutInflater 22 | import android.view.MotionEvent 23 | import android.view.View 24 | import com.eightbit.samsprung.R 25 | 26 | /** 27 | * {@inheritDoc} 28 | */ 29 | class WidgetHostView(context: Context) : AppWidgetHostView(context) { 30 | override fun getErrorView(): View { 31 | with (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater) { 32 | return inflate(R.layout.appwidget_error, this@WidgetHostView, false) 33 | } 34 | } 35 | override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { 36 | when (ev.action) { 37 | MotionEvent.ACTION_DOWN -> { } 38 | MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { } 39 | } 40 | return false 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/drawer/panels/WidgetInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.eightbit.samsprung.drawer.panels 18 | 19 | import android.content.ContentValues 20 | import com.eightbit.samsprung.drawer.panels.WidgetSettings.BaseLauncherColumns 21 | import com.eightbit.samsprung.drawer.panels.WidgetSettings.Favorites 22 | 23 | /** 24 | * Represents an item in the launcher. 25 | */ 26 | open class WidgetInfo internal constructor() { 27 | /** 28 | * The id in the settings database for this item 29 | */ 30 | var id = NO_ID.toLong() 31 | 32 | /** 33 | * [WidgetSettings.Favorites.ITEM_TYPE_APPWIDGET]. 34 | */ 35 | var itemType = 0 36 | 37 | /** 38 | * The id of the container that holds this item. For the desktop, this will be 39 | * [WidgetSettings.Favorites.CONTAINER_DESKTOP]. For the all applications folder it 40 | * will be [.NO_ID] (since it is not stored in the settings DB). For user folders 41 | * it will be the id of the folder. 42 | */ 43 | var container = NO_ID.toLong() 44 | 45 | /** 46 | * Indicates the X cell span. 47 | */ 48 | var spanX = 1 49 | 50 | /** 51 | * Indicates the Y cell span. 52 | */ 53 | var spanY = 1 54 | 55 | /** 56 | * Indicates whether the item is a gesture. 57 | */ 58 | private var isGesture = false 59 | 60 | /** 61 | * Write the fields of this item to the DB 62 | * 63 | * @param values 64 | */ 65 | open fun onAddToDatabase(values: ContentValues) { 66 | values.put(BaseLauncherColumns.ITEM_TYPE, itemType) 67 | if (!isGesture) { 68 | values.put(Favorites.CONTAINER, container) 69 | values.put(Favorites.SPANX, spanX) 70 | values.put(Favorites.SPANY, spanY) 71 | } 72 | } 73 | 74 | companion object { 75 | const val NO_ID = -1 76 | } 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/settings/Preferences.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.samsprung.settings 2 | 3 | object Preferences { 4 | const val prefsValue: String = "samsprung.preferences" 5 | const val prefLayout: String = "prefLayout" 6 | const val prefHidden: String = "prefHidden" 7 | const val prefColors: String = "prefColors" 8 | const val prefAlphas: String = "prefAlphas" 9 | const val prefWarned: String = "prefWarned" 10 | const val prefViewer: String = "prefViewer" 11 | const val prefSlider: String = "prefSlider" 12 | const val prefShifts: String = "prefShifts" 13 | const val prefThemes: String = "prefThemes" 14 | const val prefDelays: String = "prefDelays" 15 | const val prefSnooze: String = "prefSnooze" 16 | const val prefTapper: String = "prefTapper" 17 | const val prefReacts: String = "prefReacts" 18 | const val prefSearch: String = "prefSearch" 19 | const val prefRadius: String = "prefRadius" 20 | const val prefLength: String = "prefLength" 21 | const val prefRotate: String = "prefRotate" 22 | const val prefPaging: String = "prefPaging" 23 | const val prefUpdate: String = "prefUpdate" 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/speech/VoiceRecognizer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2012-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung.speech 16 | 17 | import android.annotation.SuppressLint 18 | import android.content.Intent 19 | import android.os.Bundle 20 | import android.speech.RecognitionListener 21 | import android.speech.RecognizerIntent 22 | import android.speech.SpeechRecognizer 23 | import com.eightbit.samsprung.BuildConfig 24 | 25 | @SuppressLint("SetJavaScriptEnabled") 26 | class VoiceRecognizer(private val listener: SpeechResultsListener?) : RecognitionListener { 27 | override fun onReadyForSpeech(params: Bundle) {} 28 | override fun onBeginningOfSpeech() {} 29 | override fun onRmsChanged(rmsdB: Float) {} 30 | override fun onBufferReceived(buffer: ByteArray) {} 31 | override fun onEndOfSpeech() {} 32 | override fun onError(error: Int) {} 33 | override fun onResults(results: Bundle) { 34 | val data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) 35 | val grammar = StringBuilder() 36 | data?.let { grammar.append(it[0]) } 37 | grammar.setCharAt(0, Character.toUpperCase(grammar[0])) 38 | val suggested = grammar.toString() 39 | grammar.setLength(0) 40 | listener?.onSpeechResults(suggested) 41 | } 42 | 43 | override fun onPartialResults(partialResults: Bundle) {} 44 | override fun onEvent(eventType: Int, params: Bundle) {} 45 | interface SpeechResultsListener { 46 | fun onSpeechResults(suggested: String) 47 | } 48 | 49 | fun getSpeechIntent(partial: Boolean): Intent { 50 | return Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { 51 | putExtra( 52 | RecognizerIntent.EXTRA_LANGUAGE_MODEL, 53 | RecognizerIntent.LANGUAGE_MODEL_FREE_FORM 54 | ) 55 | putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, BuildConfig.APPLICATION_ID) 56 | if (partial) { 57 | putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true) 58 | } else { 59 | putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1) 60 | } 61 | putExtra( 62 | RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 63 | java.lang.Long.valueOf(1000) 64 | ) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/update/UpdateReceiver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung.update 16 | 17 | import android.content.BroadcastReceiver 18 | import android.content.Context 19 | import android.content.Intent 20 | import android.content.pm.PackageInstaller 21 | import android.os.Parcelable 22 | import android.widget.Toast 23 | import com.eightbit.os.Version 24 | import com.eightbit.samsprung.BuildConfig 25 | import com.eightbit.samsprung.OnBroadcastService 26 | import com.eightbit.samsprung.SamSprung 27 | 28 | class UpdateReceiver : BroadcastReceiver() { 29 | 30 | private inline fun Intent.parcelable(key: String): T? = when { 31 | Version.isTiramisu -> 32 | getParcelableExtra(key, T::class.java) 33 | else -> @Suppress("deprecation") getParcelableExtra(key) as? T 34 | } 35 | 36 | override fun onReceive(context: Context, intent: Intent) { 37 | val action = intent.action 38 | intent.setPackage(context.packageName) 39 | intent.flags = 0 40 | intent.data = null 41 | when { 42 | Intent.ACTION_BOOT_COMPLETED == action 43 | || Intent.ACTION_LOCKED_BOOT_COMPLETED == action 44 | || Intent.ACTION_REBOOT == action -> { 45 | startBroadcastService(context) 46 | } 47 | Intent.ACTION_MY_PACKAGE_REPLACED == action -> { startBroadcastService(context) } 48 | !BuildConfig.GOOGLE_PLAY && SamSprung.updating == action -> { 49 | when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) { 50 | PackageInstaller.STATUS_PENDING_USER_ACTION -> { 51 | intent.parcelable(Intent.EXTRA_INTENT)?.let { 52 | startLauncherActivity( 53 | context, Intent.parseUri( 54 | it.toUri(0), Intent.URI_ALLOW_UNSAFE or Intent.URI_INTENT_SCHEME 55 | ) 56 | ) 57 | } 58 | } 59 | PackageInstaller.STATUS_SUCCESS -> { } 60 | else -> { 61 | val error = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) 62 | if (error?.contains("Session was abandoned") != true) 63 | Toast.makeText(context, error, Toast.LENGTH_LONG).show() 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | private fun startBroadcastService(context: Context) { 71 | context.startForegroundService(Intent(context, OnBroadcastService::class.java)) 72 | } 73 | 74 | private fun startLauncherActivity(context: Context, intent: Intent) { 75 | context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/samsprung/update/UpdateShimActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.samsprung.update 16 | 17 | import android.content.Intent 18 | import android.os.Bundle 19 | import androidx.appcompat.app.AppCompatActivity 20 | import com.eightbit.content.ScaledContext 21 | import com.eightbit.samsprung.R 22 | 23 | 24 | class UpdateShimActivity : AppCompatActivity() { 25 | 26 | override fun onCreate(savedInstanceState: Bundle?) { 27 | setVisible(false) 28 | ScaledContext(this).internal(2f).setTheme(R.style.Theme_Launcher_NoActionBar) 29 | super.onCreate(savedInstanceState) 30 | onNewIntent(intent) 31 | } 32 | 33 | override fun onNewIntent(intent: Intent) { 34 | super.onNewIntent(intent) 35 | intent.action?.let { 36 | UpdateManager(this).requestDownload(it) 37 | } 38 | finish() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/view/AnimatedLinearLayout.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.view 16 | 17 | import android.content.Context 18 | import android.util.AttributeSet 19 | import android.widget.LinearLayout 20 | 21 | class AnimatedLinearLayout : LinearLayout { 22 | constructor(context: Context?) : super(context) {} 23 | constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {} 24 | constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super( 25 | context, attrs, defStyle) { } 26 | 27 | interface AnimationListener { 28 | fun onAnimationStart(layout: AnimatedLinearLayout) 29 | fun onAnimationEnd(layout: AnimatedLinearLayout) 30 | } 31 | 32 | private var mAnimationListener: AnimationListener? = null 33 | fun setAnimationListener(listener: AnimationListener?) { 34 | mAnimationListener = listener 35 | } 36 | 37 | override fun onAnimationStart() { 38 | super.onAnimationStart() 39 | if (null != mAnimationListener) { 40 | mAnimationListener!!.onAnimationStart(this) 41 | } 42 | } 43 | 44 | override fun onAnimationEnd() { 45 | super.onAnimationEnd() 46 | if (null != mAnimationListener) { 47 | mAnimationListener!!.onAnimationEnd(this) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/CardFlipTransformer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Wajahat Karim 3 | Copyright 2022 AbandonedCart 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | package com.eightbit.viewpager 19 | 20 | import android.view.View 21 | import androidx.recyclerview.widget.RecyclerView 22 | import androidx.viewpager2.widget.ViewPager2 23 | import kotlin.math.abs 24 | 25 | class CardFlipTransformer : ViewPager2.PageTransformer { 26 | var isScalable = false 27 | 28 | override fun transformPage(page: View, position: Float) { 29 | val percentage = 1 - abs(position) 30 | page.cameraDistance = 30000f 31 | setVisibility(page, position) 32 | setTranslation(page) 33 | setSize(page, position, percentage) 34 | setRotation(page, position, percentage) 35 | } 36 | 37 | private fun setVisibility(page: View, position: Float) { 38 | if (position < 0.5 && position > -0.5) { 39 | page.visibility = View.VISIBLE 40 | } else { 41 | page.visibility = View.INVISIBLE 42 | } 43 | } 44 | 45 | private fun setTranslation(page: View) { 46 | val viewPager: ViewPager2 = requireViewPager(page) 47 | if (viewPager.orientation == ViewPager2.ORIENTATION_HORIZONTAL) { 48 | val scroll = viewPager.scrollX - page.left 49 | page.translationX = scroll.toFloat() 50 | } else { 51 | val scroll = viewPager.scrollY - page.top 52 | page.translationY = scroll.toFloat() 53 | } 54 | } 55 | 56 | private fun setSize(page: View, position: Float, percentage: Float) { 57 | // Do nothing, if its not scalable 58 | if (!isScalable) return 59 | val scale: Float = if (position != 0f && position != 1f) percentage else 1f 60 | page.scaleX = scale 61 | page.scaleY = scale 62 | } 63 | 64 | private fun setRotation(page: View, position: Float, percentage: Float) { 65 | val viewPager: ViewPager2 = requireViewPager(page) 66 | if (viewPager.orientation == ViewPager2.ORIENTATION_HORIZONTAL) { 67 | if (position > 0) { 68 | page.rotationY = -180 * (percentage + 1) 69 | } else { 70 | page.rotationY = 180 * (percentage + 1) 71 | } 72 | } else { 73 | if (position > 0) { 74 | page.rotationX = -180 * (percentage + 1) 75 | } else { 76 | page.rotationX = 180 * (percentage + 1) 77 | } 78 | } 79 | } 80 | 81 | private fun requireViewPager(page: View): ViewPager2 { 82 | val parent = page.parent 83 | val parentParent = parent.parent 84 | if (parent is RecyclerView && parentParent is ViewPager2) { 85 | return parentParent 86 | } 87 | throw IllegalStateException("Expected page view to be managed by a ViewPager2 instance.") 88 | } 89 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/ClockSpinTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class ClockSpinTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | page.translationX = -position * page.width 10 | if (abs(position) <= 0.5) { 11 | page.visibility = View.VISIBLE 12 | page.scaleX = 1 - abs(position) 13 | page.scaleY = 1 - abs(position) 14 | } else if (abs(position) > 0.5) { 15 | page.visibility = View.GONE 16 | } 17 | if (position < -1) { // [-Infinity,-1) 18 | // This page is way off-screen to the left. 19 | page.alpha = 0f 20 | } else if (position <= 0) { // [-1,0] 21 | page.alpha = 1f 22 | page.rotation = 360 * abs(position) 23 | } else if (position <= 1) { // (0,1] 24 | page.alpha = 1f 25 | page.rotation = -360 * abs(position) 26 | } else { // (1,+Infinity] 27 | // This page is way off-screen to the right. 28 | page.alpha = 0f 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/DepthTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class DepthTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | if (position < -1) { // [-Infinity,-1) 10 | // This page is way off-screen to the left. 11 | page.alpha = 0f 12 | } else if (position <= 0) { // [-1,0] 13 | page.alpha = 1f 14 | page.translationX = 0f 15 | page.scaleX = 1f 16 | page.scaleY = 1f 17 | } else if (position <= 1) { // (0,1] 18 | page.translationX = -position * page.width 19 | page.alpha = 1 - abs(position) 20 | page.scaleX = 1 - abs(position) 21 | page.scaleY = 1 - abs(position) 22 | } else { // (1,+Infinity] 23 | // This page is way off-screen to the right. 24 | page.alpha = 0f 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/FidgetSpinTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class FidgetSpinTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | page.translationX = -position * page.width 10 | if (abs(position) < 0.5) { 11 | page.visibility = View.VISIBLE 12 | page.scaleX = 1 - abs(position) 13 | page.scaleY = 1 - abs(position) 14 | } else if (abs(position) > 0.5) { 15 | page.visibility = View.GONE 16 | } 17 | if (position < -1) { // [-Infinity,-1) 18 | // This page is way off-screen to the left. 19 | page.alpha = 0f 20 | } else if (position <= 0) { // [-1,0] 21 | page.alpha = 1f 22 | page.rotation = 23 | 36000 * (abs(position) * abs(position) * Math.abs( 24 | position 25 | ) * abs(position) * abs(position) * abs( 26 | position 27 | ) * abs(position)) 28 | } else if (position <= 1) { // (0,1] 29 | page.alpha = 1f 30 | page.rotation = 31 | -36000 * (abs(position) * abs(position) * abs( 32 | position 33 | ) * abs(position) * abs(position) * abs( 34 | position 35 | ) * abs(position)) 36 | } else { // (1,+Infinity] 37 | // This page is way off-screen to the right. 38 | page.alpha = 0f 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/PopTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class PopTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | page.translationX = -position * page.width 10 | if (Math.abs(position) < 0.5) { 11 | page.visibility = View.VISIBLE 12 | page.scaleX = 1 - abs(position) 13 | page.scaleY = 1 - abs(position) 14 | } else if (abs(position) > 0.5) { 15 | page.visibility = View.GONE 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/SpinnerTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class SpinnerTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | page.translationX = -position * page.width 10 | page.cameraDistance = 12000f 11 | if (position < 0.5 && position > -0.5) { 12 | page.visibility = View.VISIBLE 13 | } else { 14 | page.visibility = View.INVISIBLE 15 | } 16 | if (position < -1) { // [-Infinity,-1) 17 | // This page is way off-screen to the left. 18 | page.alpha = 0f 19 | } else if (position <= 0) { // [-1,0] 20 | page.alpha = 1f 21 | page.rotationY = 900 * (1 - abs(position) + 1) 22 | } else if (position <= 1) { // (0,1] 23 | page.alpha = 1f 24 | page.rotationY = -900 * (1 - abs(position) + 1) 25 | } else { // (1,+Infinity] 26 | // This page is way off-screen to the right. 27 | page.alpha = 0f 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/viewpager/TossTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.eightbit.viewpager 2 | 3 | import android.view.View 4 | import androidx.viewpager2.widget.ViewPager2 5 | import kotlin.math.abs 6 | 7 | class TossTransformer : ViewPager2.PageTransformer { 8 | override fun transformPage(page: View, position: Float) { 9 | page.translationX = -position * page.width 10 | page.cameraDistance = 20000f 11 | if (position < 0.5 && position > -0.5) { 12 | page.visibility = View.VISIBLE 13 | } else { 14 | page.visibility = View.INVISIBLE 15 | } 16 | if (position < -1) { // [-Infinity,-1) 17 | // This page is way off-screen to the left. 18 | page.alpha = 0f 19 | } else if (position <= 0) { // [-1,0] 20 | page.alpha = 1f 21 | page.scaleX = 0.4f.coerceAtLeast(1 - abs(position)) 22 | page.scaleY = 0.4f.coerceAtLeast(1 - abs(position)) 23 | page.rotationX = 1080 * (1 - abs(position) + 1) 24 | page.translationY = -1000 * abs(position) 25 | } else if (position <= 1) { // (0,1] 26 | page.alpha = 1f 27 | page.scaleX = 0.4f.coerceAtLeast(1 - abs(position)) 28 | page.scaleY = 0.4f.coerceAtLeast(1 - abs(position)) 29 | page.rotationX = -1080 * (1 - abs(position) + 1) 30 | page.translationY = -1000 * abs(position) 31 | } else { // (1,+Infinity] 32 | // This page is way off-screen to the right. 33 | page.alpha = 0f 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/eightbit/widget/RecyclerViewTouch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * ==================================================================== 3 | * Copyright (c) 2021-2023 AbandonedCart. All rights reserved. 4 | * 5 | * See https://github.com/SamSprung/.github/blob/main/LICENSE#L5 6 | * ==================================================================== 7 | * 8 | * The license and distribution terms for any publicly available version or 9 | * derivative of this code cannot be changed. i.e. this code cannot simply be 10 | * copied and put under another distribution license 11 | * [including the GNU Public License.] Content not subject to these terms is 12 | * subject to to the terms and conditions of the Apache License, Version 2.0. 13 | */ 14 | 15 | package com.eightbit.widget 16 | 17 | import android.graphics.Canvas 18 | import androidx.recyclerview.widget.ItemTouchHelper 19 | import androidx.recyclerview.widget.RecyclerView 20 | 21 | class RecyclerViewTouch(var recyclerView: RecyclerView) { 22 | 23 | var swipeCallback: SwipeCallback? = null 24 | var swipeDirections: Int? = null 25 | 26 | private val drawerTouchCallback: ItemTouchHelper.SimpleCallback = 27 | object : ItemTouchHelper.SimpleCallback( 28 | 0, swipeDirections ?: (ItemTouchHelper.START or ItemTouchHelper.END) 29 | ) { 30 | override fun onMove( 31 | recyclerView: RecyclerView, 32 | viewHolder: RecyclerView.ViewHolder, 33 | target: RecyclerView.ViewHolder 34 | ): Boolean { 35 | return false 36 | } 37 | 38 | override fun onChildDraw( 39 | c: Canvas, 40 | recyclerView: RecyclerView, 41 | viewHolder: RecyclerView.ViewHolder, 42 | dX: Float, 43 | dY: Float, 44 | actionState: Int, 45 | isCurrentlyActive: Boolean 46 | ) { } 47 | 48 | override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { 49 | swipeCallback?.onSwiped(viewHolder, direction) 50 | } 51 | } 52 | 53 | fun setSwipeCallback(directions: Int, callback: SwipeCallback) { 54 | swipeDirections = directions 55 | swipeCallback = callback 56 | ItemTouchHelper(drawerTouchCallback).attachToRecyclerView(recyclerView) 57 | } 58 | 59 | interface SwipeCallback { 60 | fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/BlurAlgorithm.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.Canvas 5 | 6 | interface BlurAlgorithm { 7 | /** 8 | * @param bitmap bitmap to be blurred 9 | * @param blurRadius blur radius 10 | * @return blurred bitmap 11 | */ 12 | fun blur(bitmap: Bitmap?, blurRadius: Float): Bitmap? 13 | 14 | /** 15 | * Frees allocated resources 16 | */ 17 | fun destroy() 18 | 19 | /** 20 | * @return true if this algorithm returns the same instance of bitmap as it accepted 21 | * false if it creates a new instance. 22 | * 23 | * 24 | * If you return false from this method, you'll be responsible to swap bitmaps in your 25 | * [BlurAlgorithm.blur] implementation 26 | * (assign input bitmap to your field and return the instance algorithm just blurred). 27 | */ 28 | fun canModifyBitmap(): Boolean 29 | 30 | /** 31 | * Retrieve the [android.graphics.Bitmap.Config] on which the [BlurAlgorithm] 32 | * can actually work. 33 | * 34 | * @return bitmap config supported by the given blur algorithm. 35 | */ 36 | val supportedBitmapConfig: Bitmap.Config 37 | fun scaleFactor(): Float 38 | fun render(canvas: Canvas, bitmap: Bitmap) 39 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/BlurController.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.graphics.Canvas 4 | 5 | interface BlurController : BlurViewFacade { 6 | /** 7 | * Draws blurred content on given canvas 8 | * 9 | * @return true if BlurView should proceed with drawing itself and its children 10 | */ 11 | fun draw(canvas: Canvas): Boolean 12 | 13 | /** 14 | * Must be used to notify Controller when BlurView's size has changed 15 | */ 16 | fun updateBlurViewSize() 17 | 18 | /** 19 | * Frees allocated resources 20 | */ 21 | fun destroy() 22 | 23 | companion object { 24 | const val DEFAULT_SCALE_FACTOR = 6f 25 | const val DEFAULT_BLUR_RADIUS = 16f 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/BlurViewCanvas.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.Canvas 5 | 6 | // Serves purely as a marker of a Canvas used in BlurView 7 | // to skip drawing itself and other BlurViews on the View hierarchy snapshot 8 | class BlurViewCanvas(bitmap: Bitmap) : Canvas(bitmap) -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/BlurViewFacade.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.graphics.drawable.Drawable 4 | import androidx.annotation.ColorInt 5 | 6 | interface BlurViewFacade { 7 | /** 8 | * Enables/disables the blur. Enabled by default 9 | * 10 | * @param enabled true to enable, false otherwise 11 | * @return [BlurViewFacade] 12 | */ 13 | fun setBlurEnabled(enabled: Boolean): BlurViewFacade 14 | 15 | /** 16 | * Can be used to stop blur auto update or resume if it was stopped before. 17 | * Enabled by default. 18 | * 19 | * @return [BlurViewFacade] 20 | */ 21 | fun setBlurAutoUpdate(enabled: Boolean): BlurViewFacade 22 | 23 | /** 24 | * @param frameClearDrawable sets the drawable to draw before view hierarchy. 25 | * Can be used to draw Activity's window background if your root layout doesn't provide any background 26 | * Optional, by default frame is cleared with a transparent color. 27 | * @return [BlurViewFacade] 28 | */ 29 | fun setFrameClearDrawable(frameClearDrawable: Drawable?): BlurViewFacade 30 | 31 | /** 32 | * @param radius sets the blur radius 33 | * Default value is [BlurController.DEFAULT_BLUR_RADIUS] 34 | * @return [BlurViewFacade] 35 | */ 36 | fun setBlurRadius(radius: Float): BlurViewFacade 37 | 38 | /** 39 | * Sets the color overlay to be drawn on top of blurred content 40 | * 41 | * @param overlayColor int color 42 | * @return [BlurViewFacade] 43 | */ 44 | fun setOverlayColor(@ColorInt overlayColor: Int): BlurViewFacade 45 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/NoOpController.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.graphics.Canvas 4 | import android.graphics.drawable.Drawable 5 | 6 | //Used in edit mode and in case if no BlurController was set 7 | internal class NoOpController : BlurController { 8 | override fun draw(canvas: Canvas): Boolean { 9 | return true 10 | } 11 | 12 | override fun updateBlurViewSize() {} 13 | override fun destroy() {} 14 | override fun setBlurRadius(radius: Float): BlurViewFacade { 15 | return this 16 | } 17 | 18 | override fun setOverlayColor(overlayColor: Int): BlurViewFacade { 19 | return this 20 | } 21 | 22 | override fun setFrameClearDrawable(frameClearDrawable: Drawable?): BlurViewFacade { 23 | return this 24 | } 25 | 26 | override fun setBlurEnabled(enabled: Boolean): BlurViewFacade { 27 | return this 28 | } 29 | 30 | override fun setBlurAutoUpdate(enabled: Boolean): BlurViewFacade { 31 | return this 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/RenderEffectBlur.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.Canvas 6 | import android.graphics.RenderEffect 7 | import android.graphics.RenderNode 8 | import android.graphics.Shader 9 | import android.os.Build 10 | import androidx.annotation.RequiresApi 11 | 12 | /** 13 | * Leverages the new RenderEffect.createBlurEffect API to perform blur. 14 | * Hardware accelerated. 15 | * Blur is performed on a separate thread - native RenderThread. 16 | * It doesn't block the Main thread, however it can still cause an FPS drop, 17 | * because it's just in a different part of the rendering pipeline. 18 | */ 19 | @RequiresApi(Build.VERSION_CODES.S) 20 | class RenderEffectBlur : BlurAlgorithm { 21 | private val node = RenderNode("BlurViewNode") 22 | private var height = 0 23 | private var width = 0 24 | private var lastBlurRadius = 1f 25 | var fallbackAlgorithm: BlurAlgorithm? = null 26 | private var context: Context? = null 27 | override fun blur(bitmap: Bitmap?, blurRadius: Float): Bitmap { 28 | lastBlurRadius = blurRadius 29 | if (bitmap!!.height != height || bitmap.width != width) { 30 | height = bitmap.height 31 | width = bitmap.width 32 | node.setPosition(0, 0, width, height) 33 | } 34 | val canvas: Canvas = node.beginRecording() 35 | canvas.drawBitmap(bitmap, 0f, 0f, null) 36 | node.endRecording() 37 | node.setRenderEffect( 38 | RenderEffect.createBlurEffect( 39 | blurRadius, 40 | blurRadius, 41 | Shader.TileMode.MIRROR 42 | ) 43 | ) 44 | // returning not blurred bitmap, because the rendering relies on the RenderNode 45 | return bitmap 46 | } 47 | 48 | override fun destroy() { 49 | node.discardDisplayList() 50 | fallbackAlgorithm?.destroy() 51 | } 52 | 53 | override fun canModifyBitmap(): Boolean { 54 | return true 55 | } 56 | 57 | override val supportedBitmapConfig: Bitmap.Config 58 | get() = Bitmap.Config.ARGB_8888 59 | 60 | override fun scaleFactor(): Float { 61 | return BlurController.DEFAULT_SCALE_FACTOR 62 | } 63 | 64 | override fun render(canvas: Canvas, bitmap: Bitmap) { 65 | if (canvas.isHardwareAccelerated) { 66 | canvas.drawRenderNode(node) 67 | } else { 68 | if (fallbackAlgorithm == null) { 69 | fallbackAlgorithm = RenderScriptBlur(context!!) 70 | } 71 | fallbackAlgorithm!!.blur(bitmap, lastBlurRadius) 72 | fallbackAlgorithm!!.render(canvas, bitmap) 73 | } 74 | } 75 | 76 | fun setContext(context: Context) { 77 | this.context = context 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/RenderScriptBlur.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.graphics.Canvas 6 | import android.graphics.Paint 7 | import android.os.Build 8 | import android.renderscript.Allocation 9 | import android.renderscript.Element 10 | import android.renderscript.RenderScript 11 | import android.renderscript.ScriptIntrinsicBlur 12 | import androidx.annotation.RequiresApi 13 | 14 | /** 15 | * Blur using RenderScript, processed on GPU when device drivers support it. 16 | * Requires API 17+ 17 | * 18 | */ 19 | @Deprecated( 20 | """because RenderScript is deprecated and its hardware acceleration is not guaranteed. 21 | RenderEffectBlur is the best alternative at the moment.""" 22 | ) 23 | class RenderScriptBlur constructor(context: Context) : BlurAlgorithm { 24 | private val paint = Paint(Paint.FILTER_BITMAP_FLAG) 25 | private val renderScript: RenderScript 26 | private val blurScript: ScriptIntrinsicBlur 27 | private var outAllocation: Allocation? = null 28 | private var lastBitmapWidth = -1 29 | private var lastBitmapHeight = -1 30 | 31 | /** 32 | * @param context Context to create the [RenderScript] 33 | */ 34 | init { 35 | renderScript = RenderScript.create(context) 36 | blurScript = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript)) 37 | } 38 | 39 | private fun canReuseAllocation(bitmap: Bitmap): Boolean { 40 | return bitmap.height == lastBitmapHeight && bitmap.width == lastBitmapWidth 41 | } 42 | 43 | /** 44 | * @param bitmap bitmap to blur 45 | * @param blurRadius blur radius (1..25) 46 | * @return blurred bitmap 47 | */ 48 | override fun blur(bitmap: Bitmap?, blurRadius: Float): Bitmap { 49 | //Allocation will use the same backing array of pixels as bitmap if created with USAGE_SHARED flag 50 | val inAllocation = Allocation.createFromBitmap(renderScript, bitmap) 51 | if (!canReuseAllocation(bitmap!!)) { 52 | outAllocation?.destroy() 53 | outAllocation = Allocation.createTyped(renderScript, inAllocation.type) 54 | lastBitmapWidth = bitmap.width 55 | lastBitmapHeight = bitmap.height 56 | } 57 | blurScript.setRadius(blurRadius) 58 | blurScript.setInput(inAllocation) 59 | //do not use inAllocation in forEach. it will cause visual artifacts on blurred Bitmap 60 | blurScript.forEach(outAllocation) 61 | outAllocation!!.copyTo(bitmap) 62 | inAllocation.destroy() 63 | return bitmap 64 | } 65 | 66 | override fun destroy() { 67 | blurScript.destroy() 68 | renderScript.destroy() 69 | outAllocation?.destroy() 70 | } 71 | 72 | override fun canModifyBitmap(): Boolean { 73 | return true 74 | } 75 | 76 | override val supportedBitmapConfig: Bitmap.Config 77 | get() = Bitmap.Config.ARGB_8888 78 | 79 | override fun scaleFactor(): Float { 80 | return BlurController.DEFAULT_SCALE_FACTOR 81 | } 82 | 83 | override fun render(canvas: Canvas, bitmap: Bitmap) { 84 | canvas.drawBitmap(bitmap, 0f, 0f, paint) 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/eightbitlab/com/blurview/SizeScaler.kt: -------------------------------------------------------------------------------- 1 | package eightbitlab.com.blurview 2 | 3 | import eightbitlab.com.blurview.SizeScaler.Companion.ROUNDING_VALUE 4 | import kotlin.math.ceil 5 | 6 | /** 7 | * Scales width and height by [scaleFactor], 8 | * and then rounds the size proportionally so the width is divisible by [ROUNDING_VALUE] 9 | */ 10 | class SizeScaler(private val scaleFactor: Float) { 11 | fun scale(width: Int, height: Int): Size { 12 | val nonRoundedScaledWidth = downscaleSize(width.toFloat()) 13 | val scaledWidth = roundSize(nonRoundedScaledWidth) 14 | //Only width has to be aligned to ROUNDING_VALUE 15 | val roundingScaleFactor = width.toFloat() / scaledWidth 16 | //Ceiling because rounding or flooring might leave empty space on the View's bottom 17 | val scaledHeight = ceil((height / roundingScaleFactor).toDouble()).toInt() 18 | return Size(scaledWidth, scaledHeight, roundingScaleFactor) 19 | } 20 | 21 | fun isZeroSized(measuredWidth: Int, measuredHeight: Int): Boolean { 22 | return downscaleSize(measuredHeight.toFloat()) == 0 || downscaleSize(measuredWidth.toFloat()) == 0 23 | } 24 | 25 | /** 26 | * Rounds a value to the nearest divisible by [.ROUNDING_VALUE] to meet stride requirement 27 | */ 28 | private fun roundSize(value: Int): Int { 29 | return if (value % ROUNDING_VALUE == 0) { 30 | value 31 | } else value - value % ROUNDING_VALUE + ROUNDING_VALUE 32 | } 33 | 34 | private fun downscaleSize(value: Float): Int { 35 | return ceil((value / scaleFactor).toDouble()).toInt() 36 | } 37 | 38 | class Size( 39 | val width: Int, val height: Int, // TODO this is probably not needed anymore 40 | private val scaleFactor: Float 41 | ) { 42 | override fun equals(other: Any?): Boolean { 43 | if (this === other) return true 44 | if (other == null || javaClass != other.javaClass) return false 45 | val size = other as Size 46 | if (width != size.width) return false 47 | return if (height != size.height) false else size.scaleFactor.compareTo(scaleFactor) == 0 48 | } 49 | 50 | override fun hashCode(): Int { 51 | var result = width 52 | result = 31 * result + height 53 | result = 31 * result + if (scaleFactor != 0.0f) java.lang.Float.floatToIntBits( 54 | scaleFactor 55 | ) else 0 56 | return result 57 | } 58 | 59 | override fun toString(): String { 60 | return "Size{" + 61 | "width=" + width + 62 | ", height=" + height + 63 | ", scaleFactor=" + scaleFactor + 64 | '}' 65 | } 66 | } 67 | 68 | companion object { 69 | // Bitmap size should be divisible by ROUNDING_VALUE to meet stride requirement. 70 | // This will help avoiding an extra bitmap allocation when passing the bitmap to RenderScript for blur. 71 | // Usually it's 16, but on Samsung devices it's 64 for some reason. 72 | private const val ROUNDING_VALUE = 64 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/res/color/primary_text_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/color/primary_text_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night-v21/button_rippled.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_bluetooth_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_bluetooth_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_cancel_presentation_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_delete_forever_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_do_not_disturb_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_do_not_disturb_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_expand_20dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_fingerprint_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_flashlight_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_flashlight_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_github_octocat_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_insert_page_break_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_keyboard_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_launch_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_menu_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_move_up_20dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_nfc_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_nfc_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_record_voice_over_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_samsprung_24dp.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_screen_lock_rotation_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_screen_rotation_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_send_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_sound_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_sound_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_swipe_down_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_voice_over_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_wallpaper_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_widgets_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_wifi_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/ic_wifi_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/rounded_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-night/rounded_layout_themed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/button_rippled.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_appwidget_error.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/drawable/bg_appwidget_error.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_foreground.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_foreground_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bluetooth_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bluetooth_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cancel_presentation_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_forever_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_do_not_disturb_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_do_not_disturb_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expand_20dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fingerprint_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_flashlight_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_flashlight_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_github_octocat_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_google_play_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_insert_page_break_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launch_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/drawable/ic_launcher_background.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/drawable/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_move_up_20dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_nfc_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_nfc_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_paypal_donation.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_record_voice_over_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_samsprung_24dp.xml: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_screen_lock_rotation_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_screen_rotation_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_send_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sound_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sound_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_swipe_down_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_voice_over_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wallpaper_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_widget_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/drawable/ic_widget_preview.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_widgets_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wifi_off_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wifi_on_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notification_badge.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_layout_themed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/widget_preview_tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/drawable/widget_preview_tile.png -------------------------------------------------------------------------------- /app/src/main/res/layout/appwidget_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/button_cancel_sub.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 17 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/button_paypal.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 17 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/button_sponsor.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 17 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/color_panel.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 19 | 20 | 26 | 27 | 36 | 37 | 43 | 44 | 53 | 54 | 60 | 61 | 70 | 71 | 78 | 79 | 86 | 87 | 88 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /app/src/main/res/layout/configure_switch.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/donation_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 25 | 33 | 34 | 35 | 40 | 41 | 48 | 49 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_apps_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 24 | 25 | 33 | 34 | 35 | 36 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_apps_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dropdown_item_1.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/filtered_apps_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 21 | 22 | 33 | 34 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fingerprint_auth.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | 24 | 25 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_notices.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_panel.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/navigation_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 24 | 25 | 28 | 29 | 30 | 39 | 40 | 48 | 49 | 57 | 58 | 66 | 67 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /app/src/main/res/layout/notification_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 28 | 29 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/panel_picker_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 18 | 19 | 27 | 28 | 33 | 34 | 42 | 43 | 44 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/system_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 24 | 25 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toggle_state_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_options.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 22 | 23 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/widget_preview.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/menu/cover_quick_toggles.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 14 | 19 | 24 | 29 | 34 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/menu/cover_settings_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/sprung_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/sprung_icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/sprung_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-hdpi/sprung_icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/sprung_icon_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-hdpi/sprung_icon_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/sprung_icon_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-hdpi/sprung_icon_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/sprung_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-hdpi/sprung_icon_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/sprung_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-mdpi/sprung_icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/sprung_icon_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-mdpi/sprung_icon_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/sprung_icon_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-mdpi/sprung_icon_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/sprung_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-mdpi/sprung_icon_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sprung_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xhdpi/sprung_icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sprung_icon_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xhdpi/sprung_icon_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sprung_icon_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xhdpi/sprung_icon_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sprung_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xhdpi/sprung_icon_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sprung_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxhdpi/sprung_icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sprung_icon_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxhdpi/sprung_icon_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sprung_icon_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxhdpi/sprung_icon_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sprung_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxhdpi/sprung_icon_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/sprung_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxxhdpi/sprung_icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/sprung_icon_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxxhdpi/sprung_icon_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/sprung_icon_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxxhdpi/sprung_icon_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/sprung_icon_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/app/src/main/res/mipmap-xxxhdpi/sprung_icon_round.png -------------------------------------------------------------------------------- /app/src/main/res/raw/display_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF02D896 4 | #FF10C3CB 5 | #FF10C3CB 6 | #FF1DAEFC 7 | 8 | #FCCC 9 | 10 | #A9333333 11 | #66000000 12 | #BB000000 13 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/values/accessibility.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Icon 4 | Badge 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Card Flip 5 | Clock Spin 6 | Depth 7 | Fidget Spin 8 | Pop 9 | Spinner 10 | Toss 11 | None 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF02D896 4 | #FF10C3CB 5 | #FF10C3CB 6 | #FF1DAEFC 7 | 8 | #FCCC 9 | 10 | #BABBBBBB 11 | #44FFFFFF 12 | #BBFFFFFF 13 | 14 | #222 15 | 16 | #ff000000 17 | 18 | #ffffffff 19 | @color/background_light 20 | @color/background_dark 21 | #80ffffff 22 | #80000000 23 | @color/bright_foreground_light 24 | @color/bright_foreground_dark 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8dp 4 | 36dp 5 | 48dp 6 | 12dp 7 | 84dp 8 | 9 | 48dp 10 | 11 | 24dp 12 | 4dp 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/donottranslate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | SamSprung TooUI 4 | 5 | #%1$s 6 | [Logcat]: SamSprung #%1$s 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | 16 | 17 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 27 | 28 | 35 | 36 | 40 | 41 | 49 | 50 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/xml/extraction_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/xml/file_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/xml/full_backup_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | maven { url "https://jitpack.io" } 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:8.6.1' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20" 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | tasks.register('clean', Delete) { 18 | delete getLayout().getBuildDirectory() 19 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xms256m -XX:+UseParallelGC -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | # Speed up build by forcing incremental annotation processors 23 | kapt.incremental.apt=true 24 | # Caches results of configuration phase for subsequent builds 25 | org.gradle.unsafe.configuration-cache=true 26 | org.gradle.configuration-cache=true 27 | # Gradle wil run parallel compilation tasks within subprojects 28 | kotlin.parallel.tasks.in.project=true 29 | android.defaults.buildfeatures.buildconfig=true 30 | android.nonTransitiveRClass=false 31 | android.nonFinalResIds=false 32 | 33 | # Android Gradle plugin 8.0.2 34 | android.suppressUnsupportedCompileSdk=34 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamSprung/SamSprung-TooUI/905868baae1f6b57ac5a54d3f70d412ba7f170af/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Aug 27 09:21:47 BST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 3 | repositories { 4 | google() 5 | mavenCentral() 6 | maven { 7 | url "https://jitpack.io" 8 | } 9 | } 10 | } 11 | rootProject.name = "SamSprung" 12 | include ':app' 13 | --------------------------------------------------------------------------------