├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ ├── error_report.yml
│ └── feature_request.yml
└── workflows
│ ├── build_pre_release_apk.yml
│ └── build_release_apk.yml
├── .gitignore
├── .idea
├── .gitignore
├── AndroidProjectSystem.xml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── deploymentTargetDropDown.xml
├── deploymentTargetSelector.xml
├── dictionaries
│ └── Hamza.xml
├── gradle.xml
├── icon.svg
├── inspectionProfiles
│ └── Project_Default.xml
├── kotlinc.xml
├── migrations.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── .imgbotconfig
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── schemas
│ ├── app.simple.peri.database.instances.EffectsDatabase
│ │ ├── 1.json
│ │ └── 2.json
│ ├── app.simple.peri.database.instances.LastHomeWallpapersDatabase
│ │ └── 9.json
│ ├── app.simple.peri.database.instances.LastLockWallpapersDatabase
│ │ └── 9.json
│ ├── app.simple.peri.database.instances.LastWallpapersDatabase
│ │ └── 9.json
│ ├── app.simple.peri.database.instances.TagsDatabase
│ │ ├── 1.json
│ │ ├── 2.json
│ │ └── 3.json
│ └── app.simple.peri.database.instances.WallpaperDatabase
│ │ ├── 4.json
│ │ ├── 5.json
│ │ ├── 6.json
│ │ ├── 7.json
│ │ ├── 8.json
│ │ └── 9.json
└── src
│ ├── androidTest
│ └── java
│ │ └── app
│ │ └── simple
│ │ └── peri
│ │ └── ExampleInstrumentedTest.kt
│ ├── dev
│ └── res
│ │ └── values
│ │ └── strings.xml
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── ic_next-playstore.png
│ ├── java
│ │ └── app
│ │ │ └── simple
│ │ │ └── peri
│ │ │ ├── abstraction
│ │ │ ├── AbstractAutoLiveWallpaperService.kt
│ │ │ ├── AbstractAutoWallpaperService.kt
│ │ │ ├── AbstractComposeAutoWallpaperService.kt
│ │ │ └── AutoWallpaperUtils.kt
│ │ │ ├── activities
│ │ │ ├── association
│ │ │ │ └── WallpaperAssociationActivity.kt
│ │ │ └── main
│ │ │ │ ├── ComposePreferencesActivity.kt
│ │ │ │ ├── EffectsActivity.kt
│ │ │ │ ├── MainComposeActivity.kt
│ │ │ │ └── PathChooserActivity.kt
│ │ │ ├── application
│ │ │ └── PeriApplication.java
│ │ │ ├── constants
│ │ │ └── Misc.kt
│ │ │ ├── crash
│ │ │ ├── CrashReport.java
│ │ │ └── Utils.java
│ │ │ ├── data
│ │ │ └── Page.kt
│ │ │ ├── database
│ │ │ ├── converters
│ │ │ │ └── IDListConverter.kt
│ │ │ ├── dao
│ │ │ │ ├── EffectsDao.kt
│ │ │ │ ├── TagsDao.kt
│ │ │ │ └── WallpaperDao.kt
│ │ │ ├── instances
│ │ │ │ ├── EffectsDatabase.kt
│ │ │ │ ├── LastHomeWallpapersDatabase.kt
│ │ │ │ ├── LastLockWallpapersDatabase.kt
│ │ │ │ ├── LastWallpapersDatabase.kt
│ │ │ │ ├── TagsDatabase.kt
│ │ │ │ └── WallpaperDatabase.kt
│ │ │ └── migrations
│ │ │ │ └── TagsMigration.java
│ │ │ ├── extensions
│ │ │ ├── BaseComponentActivity.kt
│ │ │ ├── CompressorViewModel.kt
│ │ │ └── DoubleTapListener.kt
│ │ │ ├── factories
│ │ │ ├── FolderViewModelFactory.kt
│ │ │ └── TagsViewModelFactory.kt
│ │ │ ├── glide
│ │ │ ├── effect
│ │ │ │ ├── Effect.kt
│ │ │ │ ├── EffectLoader.kt
│ │ │ │ └── EffectsFetcher.kt
│ │ │ ├── folders
│ │ │ │ ├── ContextFolder.kt
│ │ │ │ ├── FolderFetcher.kt
│ │ │ │ └── FolderLoader.kt
│ │ │ ├── modules
│ │ │ │ ├── EffectModule.kt
│ │ │ │ ├── FolderModule.kt
│ │ │ │ ├── TagModule.kt
│ │ │ │ └── WallpaperModule.kt
│ │ │ ├── tags
│ │ │ │ ├── ContextTag.kt
│ │ │ │ ├── TagsFetcher.kt
│ │ │ │ └── TagsLoader.kt
│ │ │ ├── transitions
│ │ │ │ ├── ZoomInTransitionFactory.java
│ │ │ │ └── ZoomOut.kt
│ │ │ └── wallpaper
│ │ │ │ ├── Wallpaper.kt
│ │ │ │ ├── WallpaperFetcher.kt
│ │ │ │ └── WallpaperLoader.kt
│ │ │ ├── interfaces
│ │ │ └── WallpaperCallbacks.java
│ │ │ ├── math
│ │ │ └── Ratio.kt
│ │ │ ├── models
│ │ │ ├── DisplayDimension.kt
│ │ │ ├── Effect.java
│ │ │ ├── Folder.java
│ │ │ ├── LiveWallpaperInfo.kt
│ │ │ ├── PostWallpaperData.java
│ │ │ ├── Ratio.java
│ │ │ ├── Tag.java
│ │ │ └── Wallpaper.kt
│ │ │ ├── preferences
│ │ │ ├── CrashPreferences.kt
│ │ │ ├── MainComposePreferences.kt
│ │ │ ├── MainPreferences.kt
│ │ │ └── SharedPreferences.kt
│ │ │ ├── receivers
│ │ │ ├── BootReceiver.java
│ │ │ ├── CopyActionReceiver.kt
│ │ │ └── WallpaperActionReceiver.kt
│ │ │ ├── repository
│ │ │ └── WallpaperRepository.kt
│ │ │ ├── services
│ │ │ ├── AutoWallpaperService.kt
│ │ │ ├── LiveAutoWallpaperService.kt
│ │ │ └── NextWallpaperTileService.kt
│ │ │ ├── tools
│ │ │ └── StackBlur.java
│ │ │ ├── ui
│ │ │ ├── commons
│ │ │ │ ├── AnimatedCircularProgress.kt
│ │ │ │ ├── CircularCountdownProgress.kt
│ │ │ │ ├── DisplayDimension.kt
│ │ │ │ ├── Effect.kt
│ │ │ │ ├── Header.kt
│ │ │ │ ├── Permission.kt
│ │ │ │ ├── Preference.kt
│ │ │ │ ├── TextWithIcon.kt
│ │ │ │ ├── VignetteImage.kt
│ │ │ │ └── WallpaperListCommons.kt
│ │ │ ├── constants
│ │ │ │ └── DialogConstants.kt
│ │ │ ├── dialogs
│ │ │ │ ├── autowallpaper
│ │ │ │ │ ├── AutoWallpaperPageSelectionDialog.kt
│ │ │ │ │ ├── FoldersDialog.kt
│ │ │ │ │ ├── ScreenSelectionDialog.kt
│ │ │ │ │ ├── TagsDialog.kt
│ │ │ │ │ └── TimeSelectionDialog.kt
│ │ │ │ ├── common
│ │ │ │ │ ├── AddTagDialog.kt
│ │ │ │ │ ├── PleaseWaitDialog.kt
│ │ │ │ │ ├── PostScalingChangeDailog.kt
│ │ │ │ │ ├── ShowWarningDialog.kt
│ │ │ │ │ └── SureDialog.kt
│ │ │ │ ├── folders
│ │ │ │ │ └── FolderMenu.kt
│ │ │ │ ├── livewallpapers
│ │ │ │ │ └── LiveWallpapersMenu.kt
│ │ │ │ ├── menus
│ │ │ │ │ ├── CompressOptions.kt
│ │ │ │ │ └── WallpaperMenu.kt
│ │ │ │ ├── settings
│ │ │ │ │ ├── CacheDirectoryDialog.kt
│ │ │ │ │ ├── ConcurrencyDialog.kt
│ │ │ │ │ ├── DeveloperProfileDialog.kt
│ │ │ │ │ ├── GridSpanDialog.kt
│ │ │ │ │ ├── OrderDialog.kt
│ │ │ │ │ ├── ShowInureAppManagerDialog.kt
│ │ │ │ │ ├── ShowPositionalDialog.kt
│ │ │ │ │ └── SortDialog.kt
│ │ │ │ ├── tags
│ │ │ │ │ └── TagsMenu.kt
│ │ │ │ └── wallpaper
│ │ │ │ │ ├── EffectsDialog.kt
│ │ │ │ │ └── ScreenSelectionDialog.kt
│ │ │ ├── nav
│ │ │ │ ├── Navigation.kt
│ │ │ │ └── Routes.kt
│ │ │ ├── screens
│ │ │ │ ├── AutoWallpaper.kt
│ │ │ │ ├── Folders.kt
│ │ │ │ ├── Home.kt
│ │ │ │ ├── LiveAutoWallpaper.kt
│ │ │ │ ├── LiveWallpapers.kt
│ │ │ │ ├── Settings.kt
│ │ │ │ ├── Setup.kt
│ │ │ │ ├── Tags.kt
│ │ │ │ └── Wallpaper.kt
│ │ │ ├── settings
│ │ │ │ └── SkipColumn.kt
│ │ │ ├── subscreens
│ │ │ │ ├── TaggedWallpapers.kt
│ │ │ │ └── WallpaperList.kt
│ │ │ └── theme
│ │ │ │ ├── Color.kt
│ │ │ │ ├── Theme.kt
│ │ │ │ └── Typography.kt
│ │ │ ├── utils
│ │ │ ├── BatteryUtils.kt
│ │ │ ├── BitmapUtils.kt
│ │ │ ├── CommonUtils.kt
│ │ │ ├── ConditionUtils.kt
│ │ │ ├── DoubleTapDetector.kt
│ │ │ ├── FileUtils.kt
│ │ │ ├── ListUtils.kt
│ │ │ ├── ParcelUtils.kt
│ │ │ ├── PermissionUtils.kt
│ │ │ ├── ProcessUtils.kt
│ │ │ ├── SDCard.java
│ │ │ ├── ScreenUtils.kt
│ │ │ ├── ServiceUtils.kt
│ │ │ ├── StringUtils.kt
│ │ │ ├── WallpaperServiceNotification.kt
│ │ │ └── WallpaperSort.kt
│ │ │ ├── viewmodels
│ │ │ ├── ComposeWallpaperViewModel.kt
│ │ │ ├── EffectsViewModel.kt
│ │ │ ├── FolderDataViewModel.kt
│ │ │ ├── HomeScreenViewModel.kt
│ │ │ ├── LiveWallpapersViewModel.kt
│ │ │ ├── StateViewModel.kt
│ │ │ ├── TagsViewModel.kt
│ │ │ └── WallpaperListViewModel.kt
│ │ │ └── widgets
│ │ │ ├── NextWallpaper.kt
│ │ │ ├── NextWallpaperWidget.kt
│ │ │ └── NextWallpaperWidgetTransparent.kt
│ └── res
│ │ ├── drawable-nodpi
│ │ ├── inure.png
│ │ └── positional.png
│ │ ├── drawable
│ │ ├── ic_copy_all.xml
│ │ ├── ic_delete.xml
│ │ ├── ic_fast_forward.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_next_foreground.xml
│ │ ├── ic_peristyle.xml
│ │ ├── ic_share.xml
│ │ └── swap_vert.xml
│ │ ├── layout
│ │ ├── widget_next_wallpaper.xml
│ │ └── widget_next_wallpaper_transparent.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ ├── ic_launcher_round.xml
│ │ ├── ic_next.xml
│ │ └── ic_next_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.webp
│ │ ├── ic_launcher_round.png
│ │ ├── ic_next.webp
│ │ └── ic_next_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.webp
│ │ ├── ic_launcher_round.png
│ │ ├── ic_next.webp
│ │ └── ic_next_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.webp
│ │ ├── ic_launcher_round.png
│ │ ├── ic_next.webp
│ │ └── ic_next_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.webp
│ │ ├── ic_launcher_round.png
│ │ ├── ic_next.webp
│ │ └── ic_next_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.webp
│ │ ├── ic_launcher_round.png
│ │ ├── ic_next.webp
│ │ └── ic_next_round.webp
│ │ ├── values-ar-rSA
│ │ └── strings.xml
│ │ ├── values-de-rDE
│ │ └── strings.xml
│ │ ├── values-es-rES
│ │ └── strings.xml
│ │ ├── values-fr-rFR
│ │ └── strings.xml
│ │ ├── values-it-rIT
│ │ └── strings.xml
│ │ ├── values-pl-rPL
│ │ └── strings.xml
│ │ ├── values-ru-rRU
│ │ └── strings.xml
│ │ ├── values-tr-rTR
│ │ └── strings.xml
│ │ ├── values-vi-rVN
│ │ └── strings.xml
│ │ ├── values-zh-rCN
│ │ └── strings.xml
│ │ ├── values-zh-rTW
│ │ └── strings.xml
│ │ ├── values
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_next_background.xml
│ │ ├── non_translatable_strings.xml
│ │ └── strings.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ ├── data_extraction_rules.xml
│ │ ├── live_auto_wallpaper.xml
│ │ ├── provider_paths.xml
│ │ ├── widget_next_wallpaper.xml
│ │ └── widget_next_wallpaper_transparent.xml
│ └── test
│ └── java
│ └── app
│ └── simple
│ └── peri
│ └── ExampleUnitTest.kt
├── build.gradle
├── crowdin.yml
├── fastlane
└── metadata
│ └── android
│ ├── ar-SA
│ ├── full_description.txt
│ └── short_description.txt
│ ├── de-DE
│ ├── full_description.txt
│ └── short_description.txt
│ ├── en-US
│ ├── changelogs
│ │ ├── 107.txt
│ │ ├── 122.txt
│ │ ├── 123.txt
│ │ ├── 124.txt
│ │ ├── 126.txt
│ │ ├── 127.txt
│ │ ├── 129.txt
│ │ ├── 130.txt
│ │ ├── 131.txt
│ │ ├── 132.txt
│ │ ├── 133.txt
│ │ ├── 134.txt
│ │ ├── 136.txt
│ │ ├── 137.txt
│ │ ├── 138.txt
│ │ ├── 139.txt
│ │ ├── 140.txt
│ │ ├── 141.txt
│ │ ├── 142.txt
│ │ ├── 143.txt
│ │ ├── 144.txt
│ │ ├── 145.txt
│ │ ├── 146.txt
│ │ ├── 147.txt
│ │ ├── 148.txt
│ │ ├── 149.txt
│ │ ├── 150.txt
│ │ ├── 151.txt
│ │ ├── 152.txt
│ │ ├── 153.txt
│ │ ├── 154.txt
│ │ ├── 200.txt
│ │ ├── 201.txt
│ │ ├── 202.txt
│ │ ├── 203.txt
│ │ ├── 204.txt
│ │ ├── 205.txt
│ │ ├── 300.txt
│ │ ├── 310.txt
│ │ ├── 320.txt
│ │ ├── 330.txt
│ │ ├── 331.txt
│ │ ├── 340.txt
│ │ ├── 400.txt
│ │ ├── 500.txt
│ │ ├── 510.txt
│ │ ├── 520.txt
│ │ ├── 600.txt
│ │ ├── 610.txt
│ │ ├── 620.txt
│ │ ├── 630.txt
│ │ ├── 640.txt
│ │ ├── 700.txt
│ │ ├── 704.txt
│ │ ├── 810.txt
│ │ ├── 820.txt
│ │ ├── 830.txt
│ │ ├── 840.txt
│ │ ├── 850.txt
│ │ └── 860.txt
│ ├── full_description.txt
│ ├── images
│ │ ├── icon.png
│ │ └── phoneScreenshots
│ │ │ ├── 01.png
│ │ │ ├── 02.png
│ │ │ ├── 03.png
│ │ │ ├── 04.png
│ │ │ ├── 05.png
│ │ │ ├── 06.png
│ │ │ ├── 07.png
│ │ │ ├── 08.png
│ │ │ ├── 09.png
│ │ │ ├── 10.png
│ │ │ ├── 11.png
│ │ │ └── 12.png
│ ├── short_description.txt
│ └── title
│ ├── pl-PL
│ ├── full_description.txt
│ └── short_description.txt
│ ├── ru-RU
│ ├── full_description.txt
│ └── short_description.txt
│ ├── tr-TR
│ ├── full_description.txt
│ └── short_description.txt
│ └── zh-CN
│ ├── full_description.txt
│ └── short_description.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
├── 01.png
├── 02.png
├── 03.png
├── 04.png
├── 05.png
└── 06.gif
└── settings.gradle
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 |
3 | Thank you for considering contributing to Peristyle! Here are some guidelines to help you get
4 | started:
5 |
6 | ## How to Contribute
7 |
8 | 1. **Fork the repository**: Click the "Fork" button at the top right of the repository page.
9 | 2. **Clone your fork**: Clone your forked repository to your local machine.
10 | ```sh
11 | git clone https://github.com/your-username/Peristyle.git
12 | ```
13 | 3. **Create a branch**: Create a new branch for your contribution.
14 | 4. **Make changes**: Make your changes to the codebase.
15 | 5. **Commit your changes**: Commit your changes to your branch.
16 | ```sh
17 | git commit -m "Your message here
18 | ```
19 | 6. **Push your changes**: Push your changes to your forked repository.
20 | ```sh
21 | git push origin your-branch-name
22 | ```
23 | 7. **Submit a pull request**: Go to the original repository and click the "New pull request" button.
24 | 8. **Wait for review**: Wait for your pull request to be reviewed and merged.
25 | 9. **Sync your fork**: Sync your forked repository with the original repository.
26 | ```sh
27 | git remote add upstream
28 | git fetch upstream
29 | git checkout main
30 | git merge upstream/main
31 | git push origin main
32 | ```
33 | 10. **Delete your branch**: After your pull request has been merged, you can delete your branch.
34 | ```sh
35 | git branch -d your-branch-name
36 | ```
37 | 11. **Celebrate**: Your contribution has been merged! 🎉
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Code of Conduct
4 | url: https://github.com/Hamza417/Peristyle/blob/master/CODE_OF_CONDUCT.md
5 | about: Please read and adhere to our Code of Conduct before submitting an issue. Any violation of our Code of Conduct will result in the immediate closure of the issue and a possible ban from the repository.
6 | - name: Contribution Guidelines
7 | url: https://github.com/Hamza417/Peristyle/blob/master/.github/CONTRIBUTING.md
8 | about: Please follow our Contribution Guidelines before submitting a pull request.
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: Suggest a new feature or enhancement.
3 | title: "[Feature Request] Your Title Here"
4 | labels: [ feature request ]
5 |
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for suggesting a feature! Please provide as much detail as possible.
11 |
12 | - type: checkboxes
13 | id: confirmation
14 | attributes:
15 | label: Confirmation
16 | description: |
17 | Please confirm the following:
18 | options:
19 | - label: I have read the [Code of Conduct](https://github.com/Hamza417/Peristyle/blob/master/CODE_OF_CONDUCT.md)
20 | required: true
21 | - label: I have searched the existing issues
22 | required: true
23 |
24 | - type: input
25 | id: feature_description
26 | attributes:
27 | label: Feature Description
28 | description: A clear and concise description of what the feature is and what problem it solves.
29 | placeholder: Describe the feature here
30 | validations:
31 | required: true
32 |
33 | - type: input
34 | id: solution
35 | attributes:
36 | label: Describe the Solution
37 | description: A clear and concise description of what you want to happen.
38 | placeholder: Describe the solution here
39 | validations:
40 | required: true
41 |
42 | - type: textarea
43 | id: alternatives
44 | attributes:
45 | label: Describe Alternatives
46 | description: A clear and concise description of any alternative solutions or features you've considered.
47 | placeholder: Describe alternatives here
48 |
49 | - type: textarea
50 | id: additional_context
51 | attributes:
52 | label: Additional Context
53 | description: Add any other context or screenshots about the feature request here.
54 | placeholder: Provide additional context here
55 |
56 | - type: checkboxes
57 | id: confirmation_2
58 | attributes:
59 | label: Sufficiency Confirmation
60 | description: |
61 | Please confirm the following:
62 | options:
63 | - label: I have provided all the information requested above and deemed sufficient for the developer to address the issue
64 | required: true
65 |
--------------------------------------------------------------------------------
/.github/workflows/build_pre_release_apk.yml:
--------------------------------------------------------------------------------
1 | name: Build Pre-Release APK
2 |
3 | on:
4 | workflow_dispatch: # Allow manual triggering
5 |
6 | jobs:
7 | build:
8 | name: Build Pre-Release APK
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v4
14 |
15 | - name: Set up Java and Android SDK
16 | uses: actions/setup-java@v3
17 | with:
18 | java-version: '21'
19 | distribution: 'temurin'
20 |
21 | - name: Decode Keystore
22 | id: decode_keystore
23 | uses: timheuer/base64-to-file@v1
24 | with:
25 | fileName: 'keystore/key.jks'
26 | encodedString: ${{ secrets.SIGN_KEY }}
27 |
28 | - name: Build GitHub Release APK
29 | run: |
30 | chmod +x ./gradlew
31 | ./gradlew clean assembleProdRelease --no-build-cache --no-configuration-cache --no-daemon --rerun-tasks
32 | env:
33 | SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
34 | SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
35 | SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
36 |
37 | - name: Extract Version Name and Version Code
38 | run: |
39 | # Extract versionName and versionCode from build.gradle
40 | VERSION_NAME=$(cat app/build.gradle | grep -oP 'versionName "\K[^"]*')
41 | VERSION_CODE=$(cat app/build.gradle | grep -oP 'versionCode \K\d+')
42 |
43 | echo "Version Name: $VERSION_NAME"
44 | echo "Version Code: $VERSION_CODE"
45 |
46 | # Set these values as environment variables for later steps
47 | echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV
48 | echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV
49 |
50 | - name: Archive APKs
51 | uses: actions/upload-artifact@v4
52 | with:
53 | name: ${{ env.VERSION_NAME }} APKs
54 | path: app/build/outputs/apk/prod/release/app-prod-release.apk
55 |
--------------------------------------------------------------------------------
/.github/workflows/build_release_apk.yml:
--------------------------------------------------------------------------------
1 | name: Build Release APK
2 |
3 | on:
4 | workflow_dispatch: # Allow manual triggering
5 |
6 | jobs:
7 | build:
8 | name: Build Release APK
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Checkout code
13 | uses: actions/checkout@v4
14 |
15 | - name: Set up Java and Android SDK
16 | uses: actions/setup-java@v3
17 | with:
18 | java-version: '21'
19 | distribution: 'temurin'
20 |
21 | - name: Decode Keystore
22 | id: decode_keystore
23 | uses: timheuer/base64-to-file@v1
24 | with:
25 | fileName: 'keystore/key.jks'
26 | encodedString: ${{ secrets.SIGN_KEY }}
27 |
28 | - name: Build GitHub Release APK
29 | run: |
30 | chmod +x ./gradlew
31 | ./gradlew clean assembleProdRelease --no-build-cache --no-configuration-cache --no-daemon --rerun-tasks
32 | env:
33 | SIGNING_KEY_ALIAS: ${{ secrets.ALIAS }}
34 | SIGNING_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
35 | SIGNING_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
36 |
37 | - name: Extract Version Name and Version Code
38 | run: |
39 | # Extract versionName and versionCode from build.gradle
40 | VERSION_NAME=$(cat app/build.gradle | grep -oP 'versionName "\K[^"]*')
41 | VERSION_CODE=$(cat app/build.gradle | grep -oP 'versionCode \K\d+')
42 |
43 | echo "Version Name: $VERSION_NAME"
44 | echo "Version Code: $VERSION_CODE"
45 |
46 | # Set these values as environment variables for later steps
47 | echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV
48 | echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV
49 |
50 | - name: Set Tag
51 | run: |
52 | TAG=$(echo ${{ env.VERSION_NAME }} | tr '[:upper:]' '[:lower:]')
53 | echo "TAG=${TAG}" >> $GITHUB_ENV
54 | echo "Tag: ${TAG}" # Print tag to console
55 |
56 | - name: Archive APKs
57 | uses: actions/upload-artifact@v4
58 | with:
59 | name: ${{ env.VERSION_NAME }} APKs
60 | path: app/build/outputs/apk/prod/release/app-prod-release.apk
61 |
62 | - name: Create GitHub Release
63 | uses: softprops/action-gh-release@v2
64 | with:
65 | files: |
66 | app/**/prod/release/*.apk
67 | name: ${{ env.VERSION_NAME }} # Use the original case for the release name
68 | tag_name: ${{ env.TAG }} # Use lowercase for the tag
69 | env:
70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | /app/release/
17 | /app/prod/release/*
18 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # GitHub Copilot persisted chat sessions
5 | /copilot/chatSessions
6 |
--------------------------------------------------------------------------------
/.idea/AndroidProjectSystem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetDropDown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetSelector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Hamza.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.imgbotconfig:
--------------------------------------------------------------------------------
1 | {
2 | "schedule": "monthly", // daily|weekly|monthly
3 | "ignoredFiles": [
4 | "app/src/main/*", // ignore by folderpath
5 | ],
6 | "aggressiveCompression": "false", // true|false
7 | "compressWiki": "true", // true|false
8 | "minKBReduced": 500, // delay new prs until size reduction meets this threshold (default to 10)
9 | }
10 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /prod/release/app-prod-release.zip
3 | /play/release/app-play-release.aab
4 | /play/release/baselineProfiles/0/app-play-release.dm
5 | /play/release/baselineProfiles/1/app-play-release.dm
6 | /play/release/app-play-release.apk
7 | /play/release/output-metadata.json
8 | /dev/release/baselineProfiles/0/app-dev-release.dm
9 | /dev/release/baselineProfiles/1/app-dev-release.dm
10 | /dev/release/app-dev-release.apk
11 | /dev/release/output-metadata.json
12 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | -ignorewarnings
24 | -dontobfuscate
25 |
26 | # This is generated automatically by the Android Gradle plugin.
27 | -dontwarn javax.annotation.Nonnull
28 | -dontwarn javax.annotation.Nullable
29 | -dontwarn javax.annotation.concurrent.GuardedBy
30 | -dontwarn org.bouncycastle.cert.X509CertificateHolder
31 | -dontwarn org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
32 | -dontwarn org.bouncycastle.cms.CMSException
33 | -dontwarn org.bouncycastle.cms.CMSSignedData
34 | -dontwarn org.bouncycastle.cms.SignerId
35 | -dontwarn org.bouncycastle.cms.SignerInformation
36 | -dontwarn org.bouncycastle.cms.SignerInformationStore
37 | -dontwarn org.bouncycastle.jce.provider.BouncyCastleProvider
38 | -dontwarn org.bouncycastle.util.Selector
39 | -dontwarn org.bouncycastle.util.Store
40 | -dontwarn org.conscrypt.Conscrypt
41 | -dontwarn org.conscrypt.OpenSSLProvider
--------------------------------------------------------------------------------
/app/schemas/app.simple.peri.database.instances.TagsDatabase/1.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 1,
5 | "identityHash": "88d7a4b07350f3aef9f605e3960c71f6",
6 | "entities": [
7 | {
8 | "tableName": "tags",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `sum` TEXT, PRIMARY KEY(`name`))",
10 | "fields": [
11 | {
12 | "fieldPath": "name",
13 | "columnName": "name",
14 | "affinity": "TEXT",
15 | "notNull": true
16 | },
17 | {
18 | "fieldPath": "sum",
19 | "columnName": "sum",
20 | "affinity": "TEXT",
21 | "notNull": false
22 | }
23 | ],
24 | "primaryKey": {
25 | "autoGenerate": false,
26 | "columnNames": [
27 | "name"
28 | ]
29 | },
30 | "indices": [],
31 | "foreignKeys": []
32 | }
33 | ],
34 | "views": [],
35 | "setupQueries": [
36 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
37 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '88d7a4b07350f3aef9f605e3960c71f6')"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/schemas/app.simple.peri.database.instances.TagsDatabase/2.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 2,
5 | "identityHash": "a2a3451597f9113c956a175427784873",
6 | "entities": [
7 | {
8 | "tableName": "tags",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `ids` TEXT NOT NULL, PRIMARY KEY(`name`))",
10 | "fields": [
11 | {
12 | "fieldPath": "name",
13 | "columnName": "name",
14 | "affinity": "TEXT",
15 | "notNull": true
16 | },
17 | {
18 | "fieldPath": "sum",
19 | "columnName": "ids",
20 | "affinity": "TEXT",
21 | "notNull": true
22 | }
23 | ],
24 | "primaryKey": {
25 | "autoGenerate": false,
26 | "columnNames": [
27 | "name"
28 | ]
29 | }
30 | }
31 | ],
32 | "setupQueries": [
33 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
34 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a2a3451597f9113c956a175427784873')"
35 | ]
36 | }
37 | }
--------------------------------------------------------------------------------
/app/schemas/app.simple.peri.database.instances.TagsDatabase/3.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 3,
5 | "identityHash": "a2a3451597f9113c956a175427784873",
6 | "entities": [
7 | {
8 | "tableName": "tags",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `ids` TEXT NOT NULL, PRIMARY KEY(`name`))",
10 | "fields": [
11 | {
12 | "fieldPath": "name",
13 | "columnName": "name",
14 | "affinity": "TEXT",
15 | "notNull": true
16 | },
17 | {
18 | "fieldPath": "sum",
19 | "columnName": "ids",
20 | "affinity": "TEXT",
21 | "notNull": true
22 | }
23 | ],
24 | "primaryKey": {
25 | "autoGenerate": false,
26 | "columnNames": [
27 | "name"
28 | ]
29 | }
30 | }
31 | ],
32 | "setupQueries": [
33 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
34 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a2a3451597f9113c956a175427784873')"
35 | ]
36 | }
37 | }
--------------------------------------------------------------------------------
/app/schemas/app.simple.peri.database.instances.WallpaperDatabase/6.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 6,
5 | "identityHash": "5cf0a1dbafcccdb7f980cb894e46ddc1",
6 | "entities": [
7 | {
8 | "tableName": "wallpapers",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT, `uri` TEXT NOT NULL, `md5` TEXT NOT NULL, `prominentColor` INTEGER NOT NULL, `width` INTEGER, `height` INTEGER, `dateModified` INTEGER NOT NULL, `size` INTEGER NOT NULL, `uri_hashcode` INTEGER NOT NULL, `isSelected` INTEGER NOT NULL, PRIMARY KEY(`md5`))",
10 | "fields": [
11 | {
12 | "fieldPath": "name",
13 | "columnName": "name",
14 | "affinity": "TEXT",
15 | "notNull": false
16 | },
17 | {
18 | "fieldPath": "uri",
19 | "columnName": "uri",
20 | "affinity": "TEXT",
21 | "notNull": true
22 | },
23 | {
24 | "fieldPath": "md5",
25 | "columnName": "md5",
26 | "affinity": "TEXT",
27 | "notNull": true
28 | },
29 | {
30 | "fieldPath": "prominentColor",
31 | "columnName": "prominentColor",
32 | "affinity": "INTEGER",
33 | "notNull": true
34 | },
35 | {
36 | "fieldPath": "width",
37 | "columnName": "width",
38 | "affinity": "INTEGER",
39 | "notNull": false
40 | },
41 | {
42 | "fieldPath": "height",
43 | "columnName": "height",
44 | "affinity": "INTEGER",
45 | "notNull": false
46 | },
47 | {
48 | "fieldPath": "dateModified",
49 | "columnName": "dateModified",
50 | "affinity": "INTEGER",
51 | "notNull": true
52 | },
53 | {
54 | "fieldPath": "size",
55 | "columnName": "size",
56 | "affinity": "INTEGER",
57 | "notNull": true
58 | },
59 | {
60 | "fieldPath": "uriHashcode",
61 | "columnName": "uri_hashcode",
62 | "affinity": "INTEGER",
63 | "notNull": true
64 | },
65 | {
66 | "fieldPath": "isSelected",
67 | "columnName": "isSelected",
68 | "affinity": "INTEGER",
69 | "notNull": true
70 | }
71 | ],
72 | "primaryKey": {
73 | "autoGenerate": false,
74 | "columnNames": [
75 | "md5"
76 | ]
77 | },
78 | "indices": [],
79 | "foreignKeys": []
80 | }
81 | ],
82 | "views": [],
83 | "setupQueries": [
84 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
85 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5cf0a1dbafcccdb7f980cb894e46ddc1')"
86 | ]
87 | }
88 | }
--------------------------------------------------------------------------------
/app/schemas/app.simple.peri.database.instances.WallpaperDatabase/9.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 9,
5 | "identityHash": "c119ac5fab1f40ad7d352c977c29c77d",
6 | "entities": [
7 | {
8 | "tableName": "wallpapers",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT, `uri` TEXT NOT NULL, `file_path` TEXT NOT NULL, `id` TEXT NOT NULL, `prominentColor` INTEGER NOT NULL, `width` INTEGER, `height` INTEGER, `dateModified` INTEGER NOT NULL, `size` INTEGER NOT NULL, `folder_id` INTEGER NOT NULL, `isSelected` INTEGER NOT NULL, PRIMARY KEY(`id`))",
10 | "fields": [
11 | {
12 | "fieldPath": "name",
13 | "columnName": "name",
14 | "affinity": "TEXT",
15 | "notNull": false
16 | },
17 | {
18 | "fieldPath": "uri",
19 | "columnName": "uri",
20 | "affinity": "TEXT",
21 | "notNull": true
22 | },
23 | {
24 | "fieldPath": "filePath",
25 | "columnName": "file_path",
26 | "affinity": "TEXT",
27 | "notNull": true
28 | },
29 | {
30 | "fieldPath": "id",
31 | "columnName": "id",
32 | "affinity": "TEXT",
33 | "notNull": true
34 | },
35 | {
36 | "fieldPath": "prominentColor",
37 | "columnName": "prominentColor",
38 | "affinity": "INTEGER",
39 | "notNull": true
40 | },
41 | {
42 | "fieldPath": "width",
43 | "columnName": "width",
44 | "affinity": "INTEGER",
45 | "notNull": false
46 | },
47 | {
48 | "fieldPath": "height",
49 | "columnName": "height",
50 | "affinity": "INTEGER",
51 | "notNull": false
52 | },
53 | {
54 | "fieldPath": "dateModified",
55 | "columnName": "dateModified",
56 | "affinity": "INTEGER",
57 | "notNull": true
58 | },
59 | {
60 | "fieldPath": "size",
61 | "columnName": "size",
62 | "affinity": "INTEGER",
63 | "notNull": true
64 | },
65 | {
66 | "fieldPath": "folderID",
67 | "columnName": "folder_id",
68 | "affinity": "INTEGER",
69 | "notNull": true
70 | },
71 | {
72 | "fieldPath": "isSelected",
73 | "columnName": "isSelected",
74 | "affinity": "INTEGER",
75 | "notNull": true
76 | }
77 | ],
78 | "primaryKey": {
79 | "autoGenerate": false,
80 | "columnNames": [
81 | "id"
82 | ]
83 | },
84 | "indices": [],
85 | "foreignKeys": []
86 | }
87 | ],
88 | "views": [],
89 | "setupQueries": [
90 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
91 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c119ac5fab1f40ad7d352c977c29c77d')"
92 | ]
93 | }
94 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/app/simple/peri/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("app.simple.waller", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/dev/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Peristyle (Dev)
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/ic_next-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/ic_next-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/activities/association/WallpaperAssociationActivity.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.activities.association
2 |
3 | import android.graphics.BitmapFactory
4 | import android.os.Bundle
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.foundation.layout.fillMaxSize
7 | import androidx.compose.material3.Surface
8 | import androidx.compose.ui.Modifier
9 | import androidx.documentfile.provider.DocumentFile
10 | import androidx.lifecycle.lifecycleScope
11 | import androidx.navigation.compose.rememberNavController
12 | import app.simple.peri.extensions.BaseComponentActivity
13 | import app.simple.peri.preferences.SharedPreferences
14 | import app.simple.peri.ui.screens.Wallpaper
15 | import app.simple.peri.ui.theme.PeristyleTheme
16 | import kotlinx.coroutines.Dispatchers
17 | import kotlinx.coroutines.launch
18 | import kotlinx.coroutines.withContext
19 | import java.io.File
20 | import java.io.FileOutputStream
21 | import java.io.InputStream
22 | import app.simple.peri.models.Wallpaper as ModelWallpaper
23 |
24 | class WallpaperAssociationActivity : BaseComponentActivity() {
25 |
26 | override fun onCreate(savedInstanceState: Bundle?) {
27 | super.onCreate(savedInstanceState)
28 | SharedPreferences.init(applicationContext)
29 |
30 | lifecycleScope.launch(Dispatchers.IO) {
31 | val wallpaper = ModelWallpaper()
32 | contentResolver.openInputStream(intent.data!!)?.use { inputStream ->
33 | val documentFile = DocumentFile.fromSingleUri(this@WallpaperAssociationActivity, intent.data!!)
34 | wallpaper.filePath = copyFileToCache(inputStream, documentFile!!.name!!).absolutePath
35 | }
36 |
37 | wallpaper.uri = intent.data.toString()
38 | wallpaper.name = wallpaper.getFile().name
39 | wallpaper.dateModified = wallpaper.getFile().lastModified()
40 | wallpaper.size = wallpaper.getFile().length()
41 |
42 | val options = BitmapFactory.Options()
43 | options.inJustDecodeBounds = true
44 | BitmapFactory.decodeFile(wallpaper.filePath, options)
45 | wallpaper.width = options.outWidth
46 | wallpaper.height = options.outHeight
47 |
48 | withContext(Dispatchers.Main) {
49 | setContent {
50 | val navController = rememberNavController()
51 | PeristyleTheme {
52 | Surface(
53 | modifier = Modifier.fillMaxSize()
54 | ) {
55 | Wallpaper(navController, wallpaper)
56 | }
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
63 | private fun copyFileToCache(inputStream: InputStream, fileName: String): File {
64 | val cacheDir = cacheDir
65 | val cacheFile = File(cacheDir, fileName)
66 | inputStream.use { input ->
67 | FileOutputStream(cacheFile).use { output ->
68 | input.copyTo(output)
69 | }
70 | }
71 |
72 | return cacheFile
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/activities/main/ComposePreferencesActivity.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.activities.main
2 |
3 | import android.os.Bundle
4 | import androidx.activity.compose.setContent
5 | import androidx.compose.foundation.layout.fillMaxSize
6 | import androidx.compose.material3.Surface
7 | import androidx.compose.ui.Modifier
8 | import app.simple.peri.extensions.BaseComponentActivity
9 | import app.simple.peri.preferences.SharedPreferences
10 | import app.simple.peri.ui.screens.Settings
11 | import app.simple.peri.ui.theme.PeristyleTheme
12 |
13 | class ComposePreferencesActivity : BaseComponentActivity() {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | SharedPreferences.init(applicationContext)
18 |
19 | setContent {
20 | PeristyleTheme {
21 | Surface(
22 | modifier = Modifier.fillMaxSize()
23 | ) {
24 | Settings()
25 | }
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/application/PeriApplication.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.application;
2 |
3 | import android.app.Application;
4 |
5 | import com.google.android.material.color.DynamicColors;
6 |
7 | public class PeriApplication extends Application {
8 |
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | DynamicColors.applyToActivitiesIfAvailable(this);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/constants/Misc.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.constants
2 |
3 | object Misc {
4 | const val BLUR_TIMES = 4
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/crash/Utils.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.crash;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.File;
7 | import java.io.FileReader;
8 | import java.io.FileWriter;
9 | import java.io.IOException;
10 | import java.text.SimpleDateFormat;
11 | import java.util.Date;
12 |
13 | public class Utils {
14 | public static void create(String text, File path) {
15 | try {
16 | FileWriter writer = new FileWriter(path);
17 | writer.write(text);
18 | writer.close();
19 | } catch (IOException ignored) {
20 | }
21 | }
22 |
23 | @SuppressLint ("SimpleDateFormat")
24 | public static String getTimeStamp() {
25 | return new SimpleDateFormat("yyyyMMdd_HH-mm").format(new Date());
26 | }
27 |
28 | public static String read(File file) {
29 | BufferedReader buf = null;
30 | try {
31 | buf = new BufferedReader(new FileReader(file));
32 |
33 | StringBuilder stringBuilder = new StringBuilder();
34 | String line;
35 | while ((line = buf.readLine()) != null) {
36 | stringBuilder.append(line).append("\n");
37 | }
38 |
39 | return stringBuilder.toString().trim();
40 | } catch (IOException ignored) {
41 | } finally {
42 | try {
43 | if (buf != null) {
44 | buf.close();
45 | }
46 | } catch (IOException e) {
47 | e.printStackTrace();
48 | }
49 | }
50 | return null;
51 | }
52 |
53 | public static Throwable getCause(Throwable e) {
54 | Throwable cause;
55 | Throwable result = e;
56 |
57 | while (null != (cause = result.getCause()) && (result != cause)) {
58 | result = cause;
59 | }
60 | return result;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/data/Page.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.data
2 |
3 | data class Page(
4 | val id: Int,
5 | val isVisible: Boolean
6 | )
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/converters/IDListConverter.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.converters
2 |
3 | import androidx.room.TypeConverter
4 |
5 | class IDListConverter {
6 | @TypeConverter
7 | fun fromIDList(md5List: HashSet?): String {
8 | return md5List?.joinToString(",") ?: ""
9 | }
10 |
11 | @TypeConverter
12 | fun toIDList(md5String: String): HashSet {
13 | return md5String.split(",").toHashSet()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/dao/EffectsDao.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Delete
5 | import androidx.room.Insert
6 | import androidx.room.OnConflictStrategy
7 | import androidx.room.Query
8 | import app.simple.peri.models.Effect
9 |
10 | @Dao
11 | interface EffectsDao {
12 | @Query("SELECT * FROM effects")
13 | fun getAllEffects(): List
14 |
15 | @Query("SELECT * FROM effects WHERE id = :id")
16 | fun getEffectById(id: Int): Effect
17 |
18 | @Insert(onConflict = OnConflictStrategy.REPLACE)
19 | fun insertEffect(effect: Effect)
20 |
21 | @Delete
22 | fun deleteEffect(effect: Effect)
23 |
24 | @Query("DELETE FROM effects")
25 | fun deleteAllEffects()
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/dao/TagsDao.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.dao
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Delete
5 | import androidx.room.Insert
6 | import androidx.room.OnConflictStrategy
7 | import androidx.room.Query
8 | import app.simple.peri.models.Tag
9 |
10 | @Dao
11 | interface TagsDao {
12 | @Query("SELECT * FROM tags")
13 | fun getAllTags(): List
14 |
15 | @Query("SELECT * FROM tags WHERE name = :id")
16 | fun getTagByID(id: String): Tag
17 |
18 | /**
19 | * Get all tag names whose sum contains the given md5
20 | *
21 | * @param id The md5 to search for
22 | */
23 | @Query("SELECT name FROM tags WHERE ids LIKE '%' || :id || '%'")
24 | fun getTagNamesByID(id: String): List
25 |
26 | @Query("SELECT EXISTS(SELECT 1 FROM tags WHERE name = :id)")
27 | fun isTagExists(id: String): Boolean
28 |
29 | @Insert(onConflict = OnConflictStrategy.REPLACE)
30 | fun insertTag(tag: Tag)
31 |
32 | @Delete
33 | fun deleteTag(tag: Tag)
34 |
35 | @Query("DELETE FROM tags")
36 | fun deleteAllTags()
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/EffectsDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.EffectsDao
8 | import app.simple.peri.models.Effect
9 | import app.simple.peri.utils.ConditionUtils.invert
10 |
11 | @Database(entities = [Effect::class], version = 2)
12 | abstract class EffectsDatabase : RoomDatabase() {
13 | abstract fun effectsDao(): EffectsDao
14 |
15 | companion object {
16 | private const val DATABASE_NAME = "effects"
17 | private var instance: EffectsDatabase? = null
18 |
19 | @Synchronized
20 | fun getInstance(context: Context): EffectsDatabase? {
21 | kotlin.runCatching {
22 | if (instance!!.isOpen.invert()) {
23 | instance = Room.databaseBuilder(context, EffectsDatabase::class.java, DATABASE_NAME)
24 | .build()
25 | }
26 | }.getOrElse {
27 | instance = Room.databaseBuilder(context, EffectsDatabase::class.java, DATABASE_NAME).build()
28 | }
29 |
30 | return instance
31 | }
32 |
33 | fun destroy() {
34 | instance?.close()
35 | instance = null
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/LastHomeWallpapersDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.WallpaperDao
8 | import app.simple.peri.models.Wallpaper
9 | import app.simple.peri.utils.ConditionUtils.invert
10 |
11 | @Database(entities = [Wallpaper::class], version = 9)
12 | abstract class LastHomeWallpapersDatabase : RoomDatabase() {
13 |
14 | abstract fun wallpaperDao(): WallpaperDao
15 |
16 | companion object {
17 | private const val DB_NAME = "wallpapers_last_random_home"
18 |
19 | private var instance: LastHomeWallpapersDatabase? = null
20 |
21 | @Synchronized
22 | fun getInstance(context: Context): LastHomeWallpapersDatabase? {
23 | kotlin.runCatching {
24 | if (instance!!.isOpen.invert()) {
25 | instance = Room.databaseBuilder(context, LastHomeWallpapersDatabase::class.java, DB_NAME)
26 | .build()
27 | }
28 | }.getOrElse {
29 | instance = Room.databaseBuilder(context, LastHomeWallpapersDatabase::class.java, DB_NAME)
30 | .build()
31 | }
32 |
33 | return instance
34 | }
35 |
36 | @Synchronized
37 | fun wipeDatabase(context: Context) {
38 | kotlin.runCatching {
39 | instance?.clearAllTables()
40 | }.getOrElse {
41 | Room.databaseBuilder(context, LastHomeWallpapersDatabase::class.java, DB_NAME)
42 | .build()
43 | .clearAllTables()
44 | }
45 | }
46 |
47 | @Synchronized
48 | fun destroyInstance() {
49 | instance = null
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/LastLockWallpapersDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.WallpaperDao
8 | import app.simple.peri.models.Wallpaper
9 | import app.simple.peri.utils.ConditionUtils.invert
10 |
11 | @Database(entities = [Wallpaper::class], version = 9)
12 |
13 | abstract class LastLockWallpapersDatabase : RoomDatabase() {
14 | abstract fun wallpaperDao(): WallpaperDao
15 |
16 | companion object {
17 | private const val DB_NAME = "wallpapers_last_random_lock"
18 |
19 | private var instance: LastLockWallpapersDatabase? = null
20 |
21 | @Synchronized
22 | fun getInstance(context: Context): LastLockWallpapersDatabase? {
23 | kotlin.runCatching {
24 | if (instance!!.isOpen.invert()) {
25 | instance = Room.databaseBuilder(context, LastLockWallpapersDatabase::class.java, DB_NAME)
26 |
27 | .build()
28 | }
29 | }.getOrElse {
30 | instance = Room.databaseBuilder(context, LastLockWallpapersDatabase::class.java, DB_NAME)
31 | .build()
32 | }
33 |
34 | return instance
35 | }
36 |
37 | @Synchronized
38 | fun wipeDatabase(context: Context) {
39 | kotlin.runCatching {
40 | instance?.clearAllTables()
41 | }.getOrElse {
42 | Room.databaseBuilder(context, LastLockWallpapersDatabase::class.java, DB_NAME)
43 | .build()
44 | .clearAllTables()
45 | }
46 | }
47 |
48 | @Synchronized
49 | fun destroyInstance() {
50 | instance = null
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/LastWallpapersDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.WallpaperDao
8 | import app.simple.peri.models.Wallpaper
9 | import app.simple.peri.utils.ConditionUtils.invert
10 |
11 | @Database(entities = [Wallpaper::class], version = 9)
12 | abstract class LastWallpapersDatabase : RoomDatabase() {
13 |
14 | abstract fun wallpaperDao(): WallpaperDao
15 |
16 | companion object {
17 | private const val DB_NAME = "wallpapers_last_random"
18 |
19 | private var instance: LastWallpapersDatabase? = null
20 |
21 | @Synchronized
22 | fun getInstance(context: Context): LastWallpapersDatabase? {
23 | kotlin.runCatching {
24 | if (instance!!.isOpen.invert()) {
25 | instance = Room.databaseBuilder(context, LastWallpapersDatabase::class.java, DB_NAME)
26 |
27 | .build()
28 | }
29 | }.getOrElse {
30 | instance = Room.databaseBuilder(context, LastWallpapersDatabase::class.java, DB_NAME)
31 | .build()
32 | }
33 |
34 | return instance
35 | }
36 |
37 | @Synchronized
38 | fun wipeDatabase(context: Context) {
39 | kotlin.runCatching {
40 | instance?.clearAllTables()
41 | }.getOrElse {
42 | Room.databaseBuilder(context, LastWallpapersDatabase::class.java, DB_NAME)
43 | .build()
44 | .clearAllTables()
45 | }
46 | }
47 |
48 | @Synchronized
49 | fun destroyInstance() {
50 | instance = null
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/TagsDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.TagsDao
8 | import app.simple.peri.database.migrations.TagsMigration
9 | import app.simple.peri.models.Tag
10 | import app.simple.peri.utils.ConditionUtils.invert
11 |
12 | @Database(
13 | entities = [Tag::class],
14 | version = 3,
15 | )
16 | abstract class TagsDatabase : RoomDatabase() {
17 | abstract fun tagsDao(): TagsDao
18 |
19 | companion object {
20 | private const val DATABASE_NAME = "tags"
21 | private var instance: TagsDatabase? = null
22 |
23 | @Synchronized
24 | fun getInstance(context: Context): TagsDatabase? {
25 | kotlin.runCatching {
26 | if (instance!!.isOpen.invert()) {
27 | instance = Room.databaseBuilder(context, TagsDatabase::class.java, DATABASE_NAME)
28 | .addMigrations(TagsMigration(2, 3))
29 | .build()
30 | }
31 | }.getOrElse {
32 | instance = Room.databaseBuilder(context, TagsDatabase::class.java, DATABASE_NAME)
33 | .addMigrations(TagsMigration(2, 3))
34 | .build()
35 | }
36 |
37 | return instance
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/instances/WallpaperDatabase.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.instances
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 | import app.simple.peri.database.dao.WallpaperDao
8 | import app.simple.peri.models.Wallpaper
9 | import app.simple.peri.utils.ConditionUtils.invert
10 |
11 | @Database(entities = [Wallpaper::class], version = 9)
12 | abstract class WallpaperDatabase : RoomDatabase() {
13 | abstract fun wallpaperDao(): WallpaperDao
14 |
15 | companion object {
16 | private const val DATABASE_NAME = "wallpapers"
17 | private var instance: WallpaperDatabase? = null
18 |
19 | @Synchronized
20 | fun getInstance(context: Context): WallpaperDatabase? {
21 | kotlin.runCatching {
22 | if (instance!!.isOpen.invert()) {
23 | instance = Room.databaseBuilder(context, WallpaperDatabase::class.java, DATABASE_NAME)
24 |
25 | .build()
26 | }
27 | }.getOrElse {
28 | instance = Room.databaseBuilder(context, WallpaperDatabase::class.java, DATABASE_NAME)
29 | .build()
30 | }
31 |
32 | return instance
33 | }
34 |
35 | fun destroyInstance() {
36 | if (instance?.isOpen == true) {
37 | instance?.close()
38 | }
39 | instance = null
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/database/migrations/TagsMigration.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.database.migrations;
2 |
3 | import android.database.sqlite.SQLiteException;
4 |
5 | import androidx.room.migration.Migration;
6 | import androidx.sqlite.db.SupportSQLiteDatabase;
7 |
8 | public class TagsMigration extends Migration {
9 | public TagsMigration(int startVersion, int endVersion) {
10 | super(startVersion, endVersion);
11 | }
12 |
13 | @Override
14 | public void migrate(SupportSQLiteDatabase database) {
15 | try {
16 | // Create the new table with correct schema
17 | database.execSQL("CREATE TABLE IF NOT EXISTS `tags_new` (" +
18 | "`name` TEXT NOT NULL, " +
19 | "`ids` TEXT NOT NULL, " +
20 | "PRIMARY KEY(`name`))");
21 |
22 | // Copy the data from the old table to the new one
23 | database.execSQL("INSERT INTO `tags_new` (`name`, `ids`) " +
24 | "SELECT `name`, IFNULL(`ids`, '') FROM `tags`");
25 |
26 | // Remove the old table
27 | database.execSQL("DROP TABLE `tags`");
28 |
29 | // Rename new table to original name
30 | database.execSQL("ALTER TABLE `tags_new` RENAME TO `tags`");
31 | } catch (SQLiteException e) {
32 | // Something failed, recreate the table
33 | database.execSQL("DROP TABLE IF EXISTS `tags`");
34 | database.execSQL("DROP TABLE IF EXISTS `tags_new`");
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/extensions/BaseComponentActivity.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.extensions
2 |
3 | import android.os.Bundle
4 | import android.os.StrictMode
5 | import androidx.activity.ComponentActivity
6 |
7 | abstract class BaseComponentActivity : ComponentActivity() {
8 | override fun onCreate(savedInstanceState: Bundle?) {
9 | super.onCreate(savedInstanceState)
10 | actionBar?.hide()
11 |
12 | StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
13 | .detectAll()
14 | .penaltyLog()
15 | .build())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/extensions/CompressorViewModel.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.extensions
2 |
3 | import android.app.Application
4 | import android.graphics.Bitmap
5 | import androidx.lifecycle.AndroidViewModel
6 | import androidx.lifecycle.viewModelScope
7 | import app.simple.peri.models.Wallpaper
8 | import app.simple.peri.utils.FileUtils.toFile
9 | import id.zelory.compressor.Compressor
10 | import id.zelory.compressor.constraint.destination
11 | import id.zelory.compressor.constraint.format
12 | import id.zelory.compressor.constraint.quality
13 | import id.zelory.compressor.constraint.resolution
14 | import kotlinx.coroutines.Dispatchers
15 | import kotlinx.coroutines.launch
16 | import kotlinx.coroutines.withContext
17 | import java.io.File
18 |
19 | abstract class CompressorViewModel(application: Application) : AndroidViewModel(application) {
20 | fun compressWallpaper(wallpaper: Wallpaper, onSuccess: (Wallpaper) -> Unit) {
21 | viewModelScope.launch(Dispatchers.IO) {
22 | val file = wallpaper.filePath.toFile()
23 |
24 | // Compress the file
25 | Compressor.compress(getApplication(), file) {
26 | destination(file)
27 | quality(60)
28 | resolution(wallpaper.width!!, wallpaper.height!!)
29 | format(getFormat(wallpaper.name!!))
30 | }
31 |
32 | val wallpaper1 = onCompressionDone(wallpaper, file)
33 |
34 | withContext(Dispatchers.Main) {
35 | onSuccess(wallpaper1)
36 | }
37 |
38 | clearResidue()
39 | }
40 | }
41 |
42 | fun reduceResolution(wallpaper: Wallpaper, onSuccess: (Wallpaper) -> Unit) {
43 | viewModelScope.launch(Dispatchers.IO) {
44 | val context = getApplication()
45 | val file = wallpaper.filePath.toFile()
46 |
47 | // Compress the file
48 | Compressor.compress(context, file) {
49 | destination(file)
50 | quality(100)
51 | resolution(wallpaper.width!!.div(2), wallpaper.height!!.div(2))
52 | format(getFormat(wallpaper.name!!))
53 | }
54 |
55 | val wallpaper1 = onCompressionDone(wallpaper, file)
56 |
57 | withContext(Dispatchers.Main) {
58 | onSuccess(wallpaper1)
59 | }
60 |
61 | clearResidue()
62 | }
63 | }
64 |
65 | private fun getFormat(name: String): Bitmap.CompressFormat {
66 | @Suppress("DEPRECATION")
67 | return when (name.lowercase().substringAfterLast(".")) {
68 | "jpg" -> Bitmap.CompressFormat.JPEG
69 | "jpeg" -> Bitmap.CompressFormat.JPEG
70 | "png" -> Bitmap.CompressFormat.PNG
71 | else -> Bitmap.CompressFormat.WEBP
72 | }
73 | }
74 |
75 | private fun clearResidue() {
76 | val cacheDir = getApplication().cacheDir
77 | cacheDir.listFiles()?.forEach {
78 | if (it.absolutePath.contains("/compressor/")) {
79 | it.delete()
80 | }
81 | }
82 | }
83 |
84 | abstract fun onCompressionDone(wallpaper: Wallpaper, file: File): Wallpaper
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/extensions/DoubleTapListener.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.extensions
2 |
3 | import android.view.GestureDetector
4 | import android.view.MotionEvent
5 |
6 | @Suppress("ConvertSecondaryConstructorToPrimary")
7 | class DoubleTapListener : GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {
8 |
9 | private val onDoubleTapCallback: (MotionEvent) -> Boolean
10 |
11 | constructor(onDoubleTapCallback: (MotionEvent) -> Boolean) {
12 | this.onDoubleTapCallback = onDoubleTapCallback
13 | }
14 |
15 | override fun onDoubleTap(e: MotionEvent): Boolean {
16 | return onDoubleTapCallback(e)
17 | }
18 |
19 | // No-op implementations for other methods
20 | override fun onDown(e: MotionEvent): Boolean = false
21 | override fun onShowPress(e: MotionEvent) {}
22 | override fun onSingleTapUp(e: MotionEvent): Boolean = false
23 | override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean = false
24 | override fun onLongPress(e: MotionEvent) {}
25 | override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean = false
26 | override fun onSingleTapConfirmed(e: MotionEvent): Boolean = false
27 | override fun onDoubleTapEvent(e: MotionEvent): Boolean = false
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/factories/FolderViewModelFactory.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.factories
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.ViewModelProvider
5 | import androidx.lifecycle.viewmodel.CreationExtras
6 | import app.simple.peri.models.Folder
7 | import app.simple.peri.viewmodels.FolderDataViewModel
8 |
9 | class FolderViewModelFactory(private val hashCode: Folder) : ViewModelProvider.Factory {
10 | override fun create(modelClass: Class, extras: CreationExtras): T {
11 | val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]!!
12 | @Suppress("UNCHECKED_CAST")
13 | return FolderDataViewModel(application, hashCode) as T
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/factories/TagsViewModelFactory.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.factories
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.ViewModelProvider
5 | import androidx.lifecycle.viewmodel.CreationExtras
6 | import app.simple.peri.viewmodels.TagsViewModel
7 |
8 | class TagsViewModelFactory(private val md5: String? = null,
9 | private val tag: String? = null) : ViewModelProvider.Factory {
10 |
11 | override fun create(modelClass: Class, extras: CreationExtras): T {
12 | val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]!!
13 | @Suppress("UNCHECKED_CAST")
14 | return TagsViewModel(application, md5, tag) as T
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/effect/Effect.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.effect
2 |
3 | import android.content.Context
4 | import app.simple.peri.models.Effect
5 | import app.simple.peri.models.Wallpaper
6 |
7 | class Effect(val context: Context, val effect: Effect, val wallpaper: Wallpaper) {
8 | override fun hashCode(): Int {
9 | return effect.hashCode() + wallpaper.filePath.hashCode()
10 | }
11 |
12 | override fun equals(other: Any?): Boolean {
13 | if (this === other) return true
14 | if (javaClass != other?.javaClass) return false
15 |
16 | other as app.simple.peri.glide.effect.Effect
17 |
18 | if (context != other.context) return false
19 | if (effect != other.effect) return false
20 | if (wallpaper != other.wallpaper) return false
21 |
22 | return true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/effect/EffectLoader.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.effect
2 |
3 | import android.graphics.Bitmap
4 | import com.bumptech.glide.load.Options
5 | import com.bumptech.glide.load.model.ModelLoader
6 | import com.bumptech.glide.load.model.ModelLoaderFactory
7 | import com.bumptech.glide.load.model.MultiModelLoaderFactory
8 | import com.bumptech.glide.signature.ObjectKey
9 |
10 | class EffectLoader : ModelLoader {
11 | override fun handles(model: Effect): Boolean {
12 | return true
13 | }
14 |
15 | override fun buildLoadData(model: Effect, width: Int, height: Int, options: Options): ModelLoader.LoadData? {
16 | return ModelLoader.LoadData(ObjectKey(model), EffectsFetcher(model))
17 | }
18 |
19 | internal class Factory : ModelLoaderFactory {
20 | override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader {
21 | return EffectLoader()
22 | }
23 |
24 | override fun teardown() {
25 | /* no-op */
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/folders/ContextFolder.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.folders
2 |
3 | import android.content.Context
4 | import app.simple.peri.models.Folder
5 |
6 | class ContextFolder(val folder: Folder, val context: Context) {
7 | override fun hashCode(): Int {
8 | return folder.hashCode()
9 | }
10 |
11 | override fun equals(other: Any?): Boolean {
12 | return other is ContextFolder
13 | && other.folder.hashcode == folder.hashcode
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/folders/FolderLoader.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.folders
2 |
3 | import android.graphics.Bitmap
4 | import com.bumptech.glide.load.Options
5 | import com.bumptech.glide.load.model.ModelLoader
6 | import com.bumptech.glide.load.model.ModelLoaderFactory
7 | import com.bumptech.glide.load.model.MultiModelLoaderFactory
8 | import com.bumptech.glide.signature.ObjectKey
9 |
10 | class FolderLoader : ModelLoader {
11 | override fun buildLoadData(model: ContextFolder, width: Int, height: Int, options: Options): ModelLoader.LoadData {
12 | return ModelLoader.LoadData(ObjectKey(model), FolderFetcher(model))
13 | }
14 |
15 | override fun handles(model: ContextFolder): Boolean {
16 | return true
17 | }
18 |
19 | internal class Factory : ModelLoaderFactory {
20 | override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader {
21 | return FolderLoader()
22 | }
23 |
24 | override fun teardown() {
25 | /* no-op */
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/modules/EffectModule.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.modules
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import app.simple.peri.glide.effect.Effect
6 | import app.simple.peri.glide.effect.EffectLoader
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.Registry
9 | import com.bumptech.glide.annotation.GlideModule
10 | import com.bumptech.glide.module.LibraryGlideModule
11 |
12 | @GlideModule
13 | class EffectModule : LibraryGlideModule() {
14 | override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
15 | registry.append(Effect::class.java, Bitmap::class.java, EffectLoader.Factory())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/modules/FolderModule.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.modules
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import app.simple.peri.glide.folders.ContextFolder
6 | import app.simple.peri.glide.folders.FolderLoader
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.Registry
9 | import com.bumptech.glide.annotation.GlideModule
10 | import com.bumptech.glide.module.LibraryGlideModule
11 |
12 | @GlideModule
13 | class FolderModule : LibraryGlideModule() {
14 | override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
15 | registry.append(ContextFolder::class.java, Bitmap::class.java, FolderLoader.Factory())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/modules/TagModule.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.modules
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import app.simple.peri.glide.tags.ContextTag
6 | import app.simple.peri.glide.tags.TagsLoader
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.Registry
9 | import com.bumptech.glide.annotation.GlideModule
10 | import com.bumptech.glide.module.LibraryGlideModule
11 |
12 | @GlideModule
13 | class TagModule : LibraryGlideModule() {
14 | override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
15 | registry.append(ContextTag::class.java, Bitmap::class.java, TagsLoader.Factory())
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/modules/WallpaperModule.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.modules
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import app.simple.peri.glide.wallpaper.Wallpaper
6 | import app.simple.peri.glide.wallpaper.WallpaperLoader
7 | import com.bumptech.glide.Glide
8 | import com.bumptech.glide.GlideBuilder
9 | import com.bumptech.glide.Registry
10 | import com.bumptech.glide.annotation.GlideModule
11 | import com.bumptech.glide.load.DecodeFormat
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy
13 | import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions
14 | import com.bumptech.glide.load.resource.bitmap.Downsampler
15 | import com.bumptech.glide.module.AppGlideModule
16 | import com.bumptech.glide.request.RequestOptions
17 |
18 | @GlideModule
19 | class WallpaperModule : AppGlideModule() {
20 | override fun isManifestParsingEnabled(): Boolean {
21 | return false
22 | }
23 |
24 | override fun applyOptions(context: Context, builder: GlideBuilder) {
25 | builder.setDefaultTransitionOptions(Bitmap::class.java, BitmapTransitionOptions.withCrossFade())
26 | builder.setDefaultRequestOptions(
27 | RequestOptions()
28 | .format(DecodeFormat.PREFER_ARGB_8888)
29 | .set(Downsampler.ALLOW_HARDWARE_CONFIG, false)
30 | .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
31 | )
32 | }
33 |
34 | override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
35 | registry.append(Wallpaper::class.java, Bitmap::class.java, WallpaperLoader.Factory())
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/tags/ContextTag.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.tags
2 |
3 | import android.content.Context
4 |
5 | class ContextTag(
6 | val tag: app.simple.peri.models.Tag,
7 | val context: Context
8 | ) {
9 | override fun equals(other: Any?): Boolean {
10 | if (other is ContextTag) {
11 | return tag == other.tag && tag.sum?.count() == other.tag.sum?.count()
12 | }
13 |
14 | return false
15 | }
16 |
17 | override fun hashCode(): Int {
18 | return tag.hashCode()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/tags/TagsLoader.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.tags
2 |
3 | import android.graphics.Bitmap
4 | import com.bumptech.glide.load.Options
5 | import com.bumptech.glide.load.model.ModelLoader
6 | import com.bumptech.glide.load.model.ModelLoaderFactory
7 | import com.bumptech.glide.load.model.MultiModelLoaderFactory
8 | import com.bumptech.glide.signature.ObjectKey
9 |
10 | class TagsLoader : ModelLoader {
11 | override fun buildLoadData(model: ContextTag, width: Int, height: Int, options: Options): ModelLoader.LoadData {
12 | return ModelLoader.LoadData(ObjectKey(model), TagsFetcher(model))
13 | }
14 |
15 | override fun handles(model: ContextTag): Boolean {
16 | return true
17 | }
18 |
19 | internal class Factory : ModelLoaderFactory {
20 | override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader {
21 | return TagsLoader()
22 | }
23 |
24 | override fun teardown() {
25 | /* no-op */
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/transitions/ZoomInTransitionFactory.java:
--------------------------------------------------------------------------------
1 | // ZoomInTransitionFactory.java
2 | package app.simple.peri.glide.transitions;
3 |
4 | import android.graphics.drawable.Drawable;
5 |
6 | import com.bumptech.glide.load.DataSource;
7 | import com.bumptech.glide.request.transition.Transition;
8 | import com.bumptech.glide.request.transition.TransitionFactory;
9 | import com.bumptech.glide.request.transition.ViewPropertyTransition;
10 |
11 | public class ZoomInTransitionFactory implements TransitionFactory {
12 | private final ViewPropertyTransition.Animator animator;
13 |
14 | public ZoomInTransitionFactory() {
15 | this.animator = view -> {
16 | view.setScaleX(0.8f);
17 | view.setScaleY(0.8f);
18 | view.animate().scaleX(1f).scaleY(1f).setDuration(300).start();
19 | };
20 | }
21 |
22 | @Override
23 | public Transition build(DataSource dataSource, boolean isFirstResource) {
24 | return new ViewPropertyTransition <>(animator);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/transitions/ZoomOut.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.transitions
2 |
3 | import android.util.Log
4 | import androidx.compose.animation.core.Animatable
5 | import androidx.compose.animation.core.AnimationSpec
6 | import androidx.compose.animation.core.AnimationVector1D
7 | import androidx.compose.animation.core.CubicBezierEasing
8 | import androidx.compose.animation.core.Easing
9 | import androidx.compose.animation.core.VectorConverter
10 | import androidx.compose.animation.core.tween
11 | import androidx.compose.ui.graphics.drawscope.scale
12 | import com.bumptech.glide.integration.compose.DrawPainter
13 | import com.bumptech.glide.integration.compose.Transition
14 |
15 | val LinearOutVerySlowInEasing: Easing = CubicBezierEasing(0.0f, 0.0f, 0.0f, 1.0f)
16 |
17 | class ZoomOut(
18 | private val animationSpec: AnimationSpec
19 | ) : Transition.Factory {
20 | override fun build(): Transition = ZoomOutImpl(animationSpec)
21 |
22 | companion object : Transition.Factory {
23 | override fun build(): Transition =
24 | ZoomOutImpl(animationSpec = tween(400, easing = LinearOutVerySlowInEasing))
25 | }
26 |
27 | override fun equals(other: Any?): Boolean {
28 | if (other is ZoomOut) {
29 | return animationSpec == other.animationSpec
30 | }
31 | return false
32 | }
33 |
34 | override fun hashCode(): Int {
35 | return animationSpec.hashCode()
36 | }
37 | }
38 |
39 | internal class ZoomOutImpl(
40 | private val animationSpec: AnimationSpec
41 | ) : Transition {
42 |
43 | private companion object {
44 | const val INITIAL_SCALE = 0.75f
45 | const val FINAL_SCALE = 1F
46 | }
47 |
48 | private val animatable: Animatable =
49 | Animatable(INITIAL_SCALE, Float.VectorConverter, FINAL_SCALE)
50 |
51 | override suspend fun transition(invalidate: () -> Unit) {
52 | try {
53 | animatable.animateTo(FINAL_SCALE, animationSpec)
54 | invalidate()
55 | } finally {
56 | animatable.snapTo(FINAL_SCALE)
57 | invalidate()
58 | }
59 | }
60 |
61 | override suspend fun stop() {
62 | animatable.stop()
63 | }
64 |
65 | override val drawPlaceholder: DrawPainter = { painter, size, alpha, colorFilter ->
66 | with(painter) {
67 | scale(animatable.value) {
68 | val normalizedAlpha = (animatable.value - 0.75f) / (1f - 0.75f)
69 | draw(size, normalizedAlpha, colorFilter)
70 | }
71 | }
72 | }
73 |
74 | override val drawCurrent: DrawPainter = { painter, size, alpha, colorFilter ->
75 | with(painter) {
76 | scale(animatable.value) {
77 | val normalizedAlpha = (animatable.value - 0.75f) / (1f - 0.75f)
78 | draw(size, normalizedAlpha, colorFilter)
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/wallpaper/Wallpaper.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.wallpaper
2 |
3 | import android.content.Context
4 | import app.simple.peri.models.Wallpaper
5 |
6 | class Wallpaper(
7 | val wallpaper: Wallpaper,
8 | val context: Context) {
9 |
10 | override fun equals(other: Any?): Boolean {
11 | if (other is Wallpaper) {
12 | return wallpaper == other
13 | }
14 | return false
15 | }
16 |
17 | override fun hashCode(): Int {
18 | return wallpaper.hashCode()
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/glide/wallpaper/WallpaperLoader.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.glide.wallpaper
2 |
3 | import android.graphics.Bitmap
4 | import com.bumptech.glide.load.Options
5 | import com.bumptech.glide.load.model.ModelLoader
6 | import com.bumptech.glide.load.model.ModelLoaderFactory
7 | import com.bumptech.glide.load.model.MultiModelLoaderFactory
8 | import com.bumptech.glide.signature.ObjectKey
9 |
10 | class WallpaperLoader : ModelLoader {
11 | override fun buildLoadData(model: Wallpaper, width: Int, height: Int, options: Options): ModelLoader.LoadData? {
12 | return ModelLoader.LoadData(ObjectKey(model), WallpaperFetcher(model))
13 | }
14 |
15 | override fun handles(model: Wallpaper): Boolean {
16 | return true
17 | }
18 |
19 | internal class Factory : ModelLoaderFactory {
20 | override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader {
21 | return WallpaperLoader()
22 | }
23 |
24 | override fun teardown() {
25 | /* no-op */
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/interfaces/WallpaperCallbacks.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.interfaces;
2 |
3 | import android.view.View;
4 |
5 | import androidx.constraintlayout.widget.ConstraintLayout;
6 | import app.simple.peri.models.Wallpaper;
7 |
8 | public interface WallpaperCallbacks {
9 | void onWallpaperClicked(Wallpaper wallpaper, int position, ConstraintLayout constraintLayout);
10 |
11 | void onWallpaperLongClicked(Wallpaper wallpaper, int position, View view);
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/math/Ratio.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.math
2 |
3 | import app.simple.peri.models.Ratio
4 |
5 | object Ratio {
6 |
7 | fun greatestCommonDivisor(a: Int, b: Int): Int {
8 | return if (b == 0) a else greatestCommonDivisor(b, a % b)
9 | }
10 |
11 | fun greatestCommonDivisor(a: Long, b: Long): Long {
12 | return if (b == 0L) a else greatestCommonDivisor(b, a % b)
13 | }
14 |
15 | fun greatestCommonDivisor(a: Float, b: Float): Float {
16 | return if (b == 0f) a else greatestCommonDivisor(b, a % b)
17 | }
18 |
19 | fun greatestCommonDivisor(a: Double, b: Double): Double {
20 | return if (b == 0.0) a else greatestCommonDivisor(b, a % b)
21 | }
22 |
23 | fun calculateAspectRatio(width: Int, height: Int): Ratio {
24 | val gcd = greatestCommonDivisor(width, height)
25 | val ratioWidth = width / gcd
26 | val ratioHeight = height / gcd
27 | return Ratio(ratioWidth.toFloat(), ratioHeight.toFloat())
28 | }
29 |
30 | fun calculateAspectRatio(width: Long, height: Long): Ratio {
31 | val gcd = greatestCommonDivisor(width, height)
32 | val ratioWidth = width / gcd
33 | val ratioHeight = height / gcd
34 | return Ratio(ratioWidth.toFloat(), ratioHeight.toFloat())
35 | }
36 |
37 | fun calculateAspectRatio(width: Float, height: Float): Ratio {
38 | val gcd = greatestCommonDivisor(width, height)
39 | val ratioWidth = width / gcd
40 | val ratioHeight = height / gcd
41 | return Ratio(ratioWidth, ratioHeight)
42 | }
43 |
44 | fun calculateAspectRatio(width: Double, height: Double): Ratio {
45 | val gcd = greatestCommonDivisor(width, height)
46 | val ratioWidth = width / gcd
47 | val ratioHeight = height / gcd
48 | return Ratio(ratioWidth.toFloat(), ratioHeight.toFloat())
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/models/DisplayDimension.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.models
2 |
3 | import android.content.Context
4 | import android.os.Build
5 | import android.util.Log
6 | import android.view.WindowInsets
7 | import android.view.WindowManager
8 |
9 | data class DisplayDimension(var width: Int, var height: Int) {
10 | fun getAspectRatio(): Float {
11 | return if (width > 0 && height > 0) {
12 | width.toFloat() / height.toFloat()
13 | } else {
14 | 1f
15 | }
16 | }
17 |
18 | fun getAspectRatio(context: Context): Float {
19 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
20 | val displayMetrics = context.resources.displayMetrics
21 | val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
22 | val windowInsets = windowManager.currentWindowMetrics.windowInsets
23 | val insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
24 |
25 | width = displayMetrics.widthPixels
26 | height = displayMetrics.heightPixels + insets.top
27 | Log.i("DisplayDimension", "Width: $width, Height: $height")
28 | return width.toFloat() / height.toFloat()
29 | } else {
30 | val displayMetrics = context.resources.displayMetrics
31 | width = displayMetrics.widthPixels
32 | height = displayMetrics.heightPixels
33 | Log.i("DisplayDimension", "Width: $width, Height: $height")
34 | return width.toFloat() / height.toFloat()
35 | }
36 | }
37 |
38 | fun getReducedWidth() = width / REDUCER
39 | fun getReducedHeight() = height / REDUCER
40 |
41 | companion object {
42 | const val REDUCER = 5
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/models/LiveWallpaperInfo.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.models
2 |
3 | import android.content.pm.ResolveInfo
4 | import android.graphics.drawable.Drawable
5 |
6 | data class LiveWallpaperInfo(
7 | val name: String,
8 | val icon: Drawable,
9 | val resolveInfo: ResolveInfo
10 | )
11 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/models/PostWallpaperData.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.models;
2 |
3 | public class PostWallpaperData {
4 |
5 | private long oldSize = 0;
6 | private long newSize = 0;
7 | private int oldWidth = 0;
8 | private int oldHeight = 0;
9 | private int newWidth = 0;
10 | private int newHeight = 0;
11 | private String path = "";
12 |
13 | public PostWallpaperData() {
14 | }
15 |
16 | public PostWallpaperData(long oldSize, long newSize, int oldWidth, int oldHeight, int newWidth, int newHeight, String path) {
17 | this.oldSize = oldSize;
18 | this.newSize = newSize;
19 | this.oldWidth = oldWidth;
20 | this.oldHeight = oldHeight;
21 | this.newWidth = newWidth;
22 | this.newHeight = newHeight;
23 | this.path = path;
24 | }
25 |
26 | public long getOldSize() {
27 | return oldSize;
28 | }
29 |
30 | public void setOldSize(long oldSize) {
31 | this.oldSize = oldSize;
32 | }
33 |
34 | public long getNewSize() {
35 | return newSize;
36 | }
37 |
38 | public void setNewSize(long newSize) {
39 | this.newSize = newSize;
40 | }
41 |
42 | public int getOldWidth() {
43 | return oldWidth;
44 | }
45 |
46 | public void setOldWidth(int oldWidth) {
47 | this.oldWidth = oldWidth;
48 | }
49 |
50 | public int getOldHeight() {
51 | return oldHeight;
52 | }
53 |
54 | public void setOldHeight(int oldHeight) {
55 | this.oldHeight = oldHeight;
56 | }
57 |
58 | public int getNewWidth() {
59 | return newWidth;
60 | }
61 |
62 | public void setNewWidth(int newWidth) {
63 | this.newWidth = newWidth;
64 | }
65 |
66 | public int getNewHeight() {
67 | return newHeight;
68 | }
69 |
70 | public void setNewHeight(int newHeight) {
71 | this.newHeight = newHeight;
72 | }
73 |
74 | public String getPath() {
75 | return path;
76 | }
77 |
78 | public void setPath(String path) {
79 | this.path = path;
80 | }
81 |
82 | public float getNewAspectRatio() {
83 | return (float) newWidth / newHeight;
84 | }
85 |
86 | public float getOldAspectRatio() {
87 | return (float) oldWidth / oldHeight;
88 | }
89 |
90 | @Override
91 | public String toString() {
92 | return "PostWallpaperData{" +
93 | "oldSize=" + oldSize +
94 | ", newSize=" + newSize +
95 | ", oldWidth=" + oldWidth +
96 | ", oldHeight=" + oldHeight +
97 | ", newWidth=" + newWidth +
98 | ", newHeight=" + newHeight +
99 | ", path='" + path + '\'' +
100 | '}';
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/models/Ratio.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.models;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public class Ratio {
6 |
7 | private final float horizontal;
8 | private final float vertical;
9 |
10 | public Ratio(float horizontal, float vertical) {
11 | this.horizontal = horizontal;
12 | this.vertical = vertical;
13 | }
14 |
15 | public float getHorizontal() {
16 | return horizontal;
17 | }
18 |
19 | public float getVertical() {
20 | return vertical;
21 | }
22 |
23 | @NonNull
24 | @Override
25 | public String toString() {
26 | return "Ratio{" +
27 | "horizontal=" + horizontal +
28 | ", vertical=" + vertical +
29 | '}';
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/models/Tag.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.models;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import java.util.HashSet;
7 | import java.util.Objects;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.room.ColumnInfo;
11 | import androidx.room.Entity;
12 | import androidx.room.PrimaryKey;
13 | import androidx.room.TypeConverters;
14 | import app.simple.peri.database.converters.IDListConverter;
15 |
16 | @Entity (tableName = "tags")
17 | public class Tag implements Parcelable {
18 | @PrimaryKey
19 | @NonNull
20 | @ColumnInfo (name = "name")
21 | private String name;
22 |
23 | @ColumnInfo (name = "ids")
24 | @TypeConverters (IDListConverter.class)
25 | @NonNull
26 | private HashSet sum = new HashSet <>();
27 |
28 | public Tag(@NonNull String name, @NonNull HashSet sum) {
29 | this.name = name;
30 | this.sum = new HashSet <>(sum);
31 | }
32 |
33 | protected Tag(Parcel in) {
34 | name = Objects.requireNonNull(in.readString());
35 | }
36 |
37 | @Override
38 | public void writeToParcel(Parcel dest, int flags) {
39 | dest.writeString(name);
40 | }
41 |
42 | @Override
43 | public int describeContents() {
44 | return 0;
45 | }
46 |
47 | public static final Creator CREATOR = new Creator <>() {
48 | @Override
49 | public Tag createFromParcel(Parcel in) {
50 | return new Tag(in);
51 | }
52 |
53 | @Override
54 | public Tag[] newArray(int size) {
55 | return new Tag[size];
56 | }
57 | };
58 |
59 | @NonNull
60 | public String getName() {
61 | return name;
62 | }
63 |
64 | public void setName(@NonNull String name) {
65 | this.name = name;
66 | }
67 |
68 | public HashSet getSum() {
69 | return sum;
70 | }
71 |
72 | public void setSum(HashSet sum) {
73 | this.sum = sum;
74 | }
75 |
76 | public void addSum(String sum) {
77 | this.sum.add(sum);
78 | }
79 |
80 | @NonNull
81 | @Override
82 | public String toString() {
83 | return "Tag{" +
84 | ", tag='" + name + '\'' +
85 | ", sum=" + sum +
86 | '}';
87 | }
88 |
89 | @Override
90 | public boolean equals(Object o) {
91 | if (this == o) {
92 | return true;
93 | }
94 | if (o == null || getClass() != o.getClass()) {
95 | return false;
96 | }
97 |
98 | Tag tag1 = (Tag) o;
99 |
100 | if (!Objects.equals(name, tag1.name)) {
101 | return false;
102 | }
103 | return Objects.equals(sum, tag1.sum);
104 | }
105 |
106 | @Override
107 | public int hashCode() {
108 | int result = name.hashCode();
109 | result = 31 * result + (sum != null ? sum.hashCode() : 0);
110 | return result;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/preferences/CrashPreferences.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.preferences
2 |
3 | import android.annotation.SuppressLint
4 |
5 | @SuppressLint("UseKtx")
6 | object CrashPreferences {
7 |
8 | private const val CRASH_TIMESTAMP = "crash_timestamp"
9 | private const val CRASH_MESSAGE = "crash_message"
10 | private const val CRASH_CAUSE = "crashCause"
11 |
12 | const val CRASH_TIMESTAMP_EMPTY_DEFAULT = -1L
13 |
14 | // ---------------------------------------------------------------------------------------------------------- //
15 |
16 | fun saveCrashLog(value: Long): Boolean {
17 | return SharedPreferences.getSharedPreferences().edit().putLong(CRASH_TIMESTAMP, value).commit()
18 | }
19 |
20 | fun getCrashLog(): Long {
21 | return SharedPreferences.getSharedPreferences().getLong(CRASH_TIMESTAMP, CRASH_TIMESTAMP_EMPTY_DEFAULT)
22 | }
23 |
24 | // ---------------------------------------------------------------------------------------------------------- //
25 |
26 | fun saveMessage(value: String?): Boolean {
27 | return SharedPreferences.getSharedPreferences().edit().putString(CRASH_MESSAGE, value).commit()
28 | }
29 |
30 | fun getMessage(): String? {
31 | return SharedPreferences.getSharedPreferences().getString(CRASH_MESSAGE, null)
32 | }
33 |
34 | // ---------------------------------------------------------------------------------------------------------- //
35 |
36 | fun saveCause(value: String?): Boolean {
37 | return SharedPreferences.getSharedPreferences().edit().putString(CRASH_CAUSE, value).commit()
38 | }
39 |
40 | fun getCause(): String? {
41 | return SharedPreferences.getSharedPreferences().getString(CRASH_CAUSE, null)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/preferences/SharedPreferences.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.preferences
2 |
3 | import android.content.Context
4 | import android.content.SharedPreferences
5 | import app.simple.peri.utils.ConditionUtils.isNull
6 |
7 | object SharedPreferences {
8 |
9 | private const val PREFERENCES = "Preferences"
10 | private var sharedPreferences: SharedPreferences? = null
11 |
12 | fun init(context: Context) {
13 | if (sharedPreferences.isNull()) {
14 | sharedPreferences = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE)
15 | }
16 | }
17 |
18 | /**
19 | * Singleton to hold reference of SharedPreference.
20 | * Call [init] first before making a instance request
21 | *
22 | * @see init
23 | * @throws NullPointerException
24 | */
25 | fun getSharedPreferences(): SharedPreferences {
26 | return sharedPreferences ?: throw NullPointerException()
27 | }
28 |
29 | fun registerSharedPreferencesListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
30 | getSharedPreferences().registerOnSharedPreferenceChangeListener(listener)
31 | }
32 |
33 | fun unregisterListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
34 | getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener)
35 | }
36 |
37 | /**
38 | * Use this function to register shared preference change listener if
39 | * the current context has [SharedPreferences.OnSharedPreferenceChangeListener]
40 | * implemented.
41 | */
42 | fun SharedPreferences.OnSharedPreferenceChangeListener.registerSharedPreferenceChangeListener() {
43 | registerSharedPreferencesListener(this)
44 | }
45 |
46 | /**
47 | * Use this function to unregister shared preference change listener if
48 | * the current context has [SharedPreferences.OnSharedPreferenceChangeListener]
49 | * implemented.
50 | */
51 | fun SharedPreferences.OnSharedPreferenceChangeListener.unregisterSharedPreferenceChangeListener() {
52 | unregisterListener(this)
53 | }
54 |
55 | /**
56 | * Singleton to hold reference of SharedPreference.
57 | *
58 | * @see init
59 | */
60 | fun getSharedPreferences(context: Context): SharedPreferences {
61 | kotlin.runCatching {
62 | return sharedPreferences ?: throw NullPointerException()
63 | }.getOrElse {
64 | init(context)
65 | return sharedPreferences!!
66 | }
67 | }
68 |
69 | fun getSharedPreferencesPath(context: Context): String {
70 | return context.applicationInfo.dataDir + "/shared_prefs/" + PREFERENCES + ".xml"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/receivers/BootReceiver.java:
--------------------------------------------------------------------------------
1 | package app.simple.peri.receivers;
2 |
3 | import android.app.AlarmManager;
4 | import android.app.PendingIntent;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import app.simple.peri.BuildConfig;
11 | import app.simple.peri.preferences.MainPreferences;
12 | import app.simple.peri.preferences.SharedPreferences;
13 | import app.simple.peri.services.AutoWallpaperService;
14 |
15 | import static android.content.Context.ALARM_SERVICE;
16 |
17 | public class BootReceiver extends android.content.BroadcastReceiver {
18 | @Override
19 | public void onReceive(Context context, Intent intent) {
20 | SharedPreferences.INSTANCE.init(context.getApplicationContext());
21 |
22 | if (intent.getAction() != null) {
23 | if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
24 | try {
25 | setAutoWallpaperAlarm(context);
26 |
27 | if (BuildConfig.DEBUG) {
28 | Toast.makeText(context, "Peristyle: Auto wallpaper enabled", Toast.LENGTH_SHORT).show();
29 | }
30 |
31 | Log.d("BootReceiver", "Boot completed action received, auto wallpaper enabled");
32 | } catch (Exception e) {
33 | if (BuildConfig.DEBUG) {
34 | Toast.makeText(context, "Peristyle: Error setting auto wallpaper", Toast.LENGTH_SHORT).show();
35 | }
36 |
37 | Log.e("BootReceiver", "Error setting auto wallpaper", e);
38 | }
39 | }
40 | }
41 | }
42 |
43 | private void setAutoWallpaperAlarm(Context context) {
44 | AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
45 | Intent intent = new Intent(context.getApplicationContext(), AutoWallpaperService.class);
46 | PendingIntent pendingIntent = PendingIntent.getService(context.getApplicationContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE);
47 |
48 | // Cancel any existing alarms
49 | alarmManager.cancel(pendingIntent);
50 |
51 | if (Integer.parseInt(MainPreferences.INSTANCE.getAutoWallpaperInterval()) > 0) {
52 | int interval = Integer.parseInt(MainPreferences.INSTANCE.getAutoWallpaperInterval());
53 | alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
54 | Log.d("MainActivity", "Auto wallpaper alarm set for every " + MainPreferences.INSTANCE.getAutoWallpaperInterval() + " ms");
55 | } else {
56 | Log.d("MainActivity", "Auto wallpaper alarm cancelled");
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/receivers/CopyActionReceiver.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.receivers
2 |
3 | import android.app.NotificationManager
4 | import android.content.BroadcastReceiver
5 | import android.content.ClipData
6 | import android.content.ClipboardManager
7 | import android.content.Context
8 | import android.content.Intent
9 | import android.widget.Toast
10 | import app.simple.peri.abstraction.AbstractComposeAutoWallpaperService
11 | import app.simple.peri.utils.WallpaperServiceNotification
12 |
13 | class CopyActionReceiver : BroadcastReceiver() {
14 | override fun onReceive(context: Context, intent: Intent) {
15 | if (intent.action == AbstractComposeAutoWallpaperService.ACTION_COPY_ERROR_MESSAGE) {
16 | val message = intent.getStringExtra(AbstractComposeAutoWallpaperService.EXTRA_ERROR_MESSAGE)
17 | val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
18 | val clip = ClipData.newPlainText("Error Message", message)
19 | clipboard.setPrimaryClip(clip)
20 | Toast.makeText(context, "Error message copied to clipboard", Toast.LENGTH_SHORT).show()
21 |
22 | val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
23 | notificationManager.cancel(WallpaperServiceNotification.ERROR_NOTIFICATION_ID)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/repository/WallpaperRepository.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.repository
2 |
3 | import app.simple.peri.database.dao.WallpaperDao
4 | import app.simple.peri.models.Wallpaper
5 | import kotlinx.coroutines.flow.Flow
6 |
7 | class WallpaperRepository(private val wallpaperDao: WallpaperDao) {
8 | fun getAllWallpapers(): Flow> = wallpaperDao.getWallpapersFlow()
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/services/NextWallpaperTileService.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.services
2 |
3 | import android.content.Intent
4 | import android.service.quicksettings.TileService
5 |
6 | class NextWallpaperTileService : TileService() {
7 |
8 | override fun onClick() {
9 | super.onClick()
10 | val intent = Intent(applicationContext, AutoWallpaperService::class.java)
11 | intent.action = AutoWallpaperService.ACTION_NEXT_WALLPAPER
12 | applicationContext.startService(intent)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/AnimatedCircularProgress.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import androidx.activity.ComponentActivity
4 | import androidx.activity.compose.LocalActivity
5 | import androidx.compose.animation.core.animateFloatAsState
6 | import androidx.compose.foundation.Canvas
7 | import androidx.compose.foundation.layout.size
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.runtime.collectAsState
10 | import androidx.compose.runtime.getValue
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.geometry.Offset
13 | import androidx.compose.ui.geometry.Size
14 | import androidx.compose.ui.graphics.Brush
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.graphics.drawscope.Stroke
17 | import androidx.compose.ui.unit.dp
18 | import androidx.lifecycle.viewmodel.compose.viewModel
19 | import app.simple.peri.utils.CommonUtils.toSeconds
20 | import app.simple.peri.viewmodels.HomeScreenViewModel
21 |
22 | @Composable
23 | fun AnimatedCircularProgress(modifier: Modifier = Modifier) {
24 | val homeScreenViewModel: HomeScreenViewModel = viewModel(
25 | LocalActivity.current as ComponentActivity
26 | )
27 |
28 | val progress = homeScreenViewModel.countDownFlow
29 | .collectAsState(initial = HomeScreenViewModel.RANDOM_WALLPAPER_DELAY).value.toFloat().toSeconds()
30 | .div(HomeScreenViewModel.RANDOM_WALLPAPER_DELAY.toFloat().toSeconds())
31 | .coerceIn(0f, 1f)
32 |
33 | val animatedProgress by animateFloatAsState(targetValue = progress, label = "")
34 |
35 | Canvas(modifier = modifier.size(32.dp)) {
36 | val strokeWidth = 4.dp.toPx()
37 | val radius = size.minDimension / 2 - strokeWidth / 2
38 | val center = Offset(size.width / 2, size.height / 2)
39 |
40 | drawCircle(
41 | brush = Brush.linearGradient(
42 | colors = listOf(Color.Red, Color.Yellow, Color.Green)
43 | ),
44 | center = center,
45 | radius = radius,
46 | style = Stroke(width = strokeWidth)
47 | )
48 |
49 | drawArc(
50 | brush = Brush.linearGradient(
51 | colors = listOf(Color.Cyan, Color.Magenta, Color.Blue)
52 | ),
53 | startAngle = -90f,
54 | sweepAngle = 360 * animatedProgress,
55 | useCenter = false,
56 | topLeft = Offset(center.x - radius, center.y - radius),
57 | size = Size(radius * 2, radius * 2),
58 | style = Stroke(width = strokeWidth)
59 | )
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/CircularCountdownProgress.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import androidx.activity.ComponentActivity
4 | import androidx.activity.compose.LocalActivity
5 | import androidx.compose.foundation.layout.size
6 | import androidx.compose.material3.CircularProgressIndicator
7 | import androidx.compose.material3.MaterialTheme
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.runtime.collectAsState
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.graphics.Color
12 | import androidx.compose.ui.unit.dp
13 | import androidx.lifecycle.viewmodel.compose.viewModel
14 | import app.simple.peri.utils.CommonUtils.toSeconds
15 | import app.simple.peri.viewmodels.HomeScreenViewModel
16 |
17 | @Composable
18 | fun CircularCountdownProgress(modifier: Modifier = Modifier) {
19 | val homeScreenViewModel: HomeScreenViewModel = viewModel(
20 | LocalActivity.current as ComponentActivity
21 | )
22 |
23 | val progress = homeScreenViewModel.countDownFlow
24 | .collectAsState(initial = HomeScreenViewModel.RANDOM_WALLPAPER_DELAY).value.toFloat().toSeconds()
25 | .div(HomeScreenViewModel.RANDOM_WALLPAPER_DELAY.toFloat().toSeconds())
26 | .coerceIn(0f, 1f)
27 |
28 | CircularProgressIndicator(
29 | progress = { progress },
30 | modifier = modifier
31 | .size(32.dp),
32 | color = MaterialTheme.colorScheme.primary,
33 | strokeWidth = 4.dp,
34 | gapSize = 0.dp,
35 | trackColor = Color.Transparent
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/DisplayDimension.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import android.util.Log
4 | import android.view.ViewTreeObserver
5 | import androidx.compose.runtime.Composable
6 | import androidx.compose.runtime.DisposableEffect
7 | import androidx.compose.ui.platform.LocalView
8 | import app.simple.peri.ui.screens.displayDimension
9 |
10 | @Composable
11 | fun InitDisplayDimension() {
12 | val view = LocalView.current
13 |
14 | DisposableEffect(view) {
15 | val observer = view.viewTreeObserver
16 | val listener = object : ViewTreeObserver.OnGlobalLayoutListener {
17 | override fun onGlobalLayout() {
18 | if (observer.isAlive) {
19 | observer.removeOnGlobalLayoutListener(this)
20 | displayDimension.width = view.width
21 | displayDimension.height = view.height
22 | Log.i("InitDisplayDimension", "Width: ${displayDimension.width}, Height: ${displayDimension.height}")
23 | }
24 | }
25 | }
26 | observer.addOnGlobalLayoutListener(listener)
27 |
28 | onDispose {
29 | observer.removeOnGlobalLayoutListener(listener)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/Effect.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.os.Parcelable
6 | import androidx.activity.compose.rememberLauncherForActivityResult
7 | import androidx.activity.result.contract.ActivityResultContracts
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.runtime.LaunchedEffect
10 | import androidx.compose.ui.platform.LocalContext
11 | import androidx.core.content.IntentCompat
12 | import app.simple.peri.activities.main.EffectsActivity
13 | import app.simple.peri.models.Effect
14 | import app.simple.peri.models.Wallpaper
15 |
16 | @Composable
17 | fun LaunchEffectActivity(wallpaper: Wallpaper, onEffect: (Effect) -> Unit, onCanceled: () -> Unit) {
18 | val context = LocalContext.current
19 | val launcher = rememberLauncherForActivityResult(
20 | contract = ActivityResultContracts.StartActivityForResult()
21 | ) { result ->
22 | if (result.resultCode == Activity.RESULT_OK) {
23 | val effect = IntentCompat.getParcelableExtra(result.data!!, "effect", Effect::class.java)
24 | onEffect(effect!!)
25 | } else {
26 | onCanceled()
27 | }
28 | }
29 |
30 | // Launch the effect activity
31 | LaunchedEffect(Unit) {
32 | val intent = Intent(context, EffectsActivity::class.java)
33 | intent.putExtra("wallpaper", wallpaper as Parcelable)
34 | launcher.launch(intent)
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/Permission.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.util.Log
6 | import androidx.activity.compose.rememberLauncherForActivityResult
7 | import androidx.activity.result.contract.ActivityResultContracts
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.runtime.LaunchedEffect
10 | import androidx.compose.ui.platform.LocalContext
11 | import app.simple.peri.activities.main.PathChooserActivity
12 |
13 | @Composable
14 | fun FolderBrowser(onCancel: () -> Unit, onStorageGranted: (String) -> Unit) {
15 | val context = LocalContext.current
16 | val launcher = rememberLauncherForActivityResult(
17 | contract = ActivityResultContracts.StartActivityForResult()
18 | ) { result ->
19 | if (result.resultCode == Activity.RESULT_OK) {
20 | val chosenPath = result.data?.getStringExtra("chosen_path")
21 | ?: return@rememberLauncherForActivityResult
22 | Log.i("PathChooserActivity", "Chosen path: $chosenPath")
23 | onStorageGranted(chosenPath)
24 | } else {
25 | onCancel()
26 | }
27 | }
28 |
29 | // Launch the directory selection intent
30 | LaunchedEffect(Unit) {
31 | val intent = Intent(context, PathChooserActivity::class.java)
32 | launcher.launch(intent)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/TextWithIcon.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import androidx.compose.foundation.layout.Row
4 | import androidx.compose.foundation.layout.Spacer
5 | import androidx.compose.foundation.layout.size
6 | import androidx.compose.material3.Icon
7 | import androidx.compose.material3.MaterialTheme
8 | import androidx.compose.material3.Text
9 | import androidx.compose.runtime.Composable
10 | import androidx.compose.ui.Alignment
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.graphics.Color
13 | import androidx.compose.ui.graphics.vector.ImageVector
14 | import androidx.compose.ui.unit.dp
15 |
16 | @Composable
17 | fun TextWithIcon(imageVector: ImageVector, tint: Color, text: String, modifier: Modifier) {
18 | Row(
19 | modifier = modifier
20 | ) {
21 | Icon(
22 | imageVector = imageVector,
23 | contentDescription = null,
24 | modifier = Modifier
25 | .size(16.dp)
26 | .align(Alignment.CenterVertically),
27 | tint = tint
28 | )
29 | Spacer(
30 | modifier = Modifier.size(4.dp)
31 | )
32 | Text(
33 | text = text,
34 | style = MaterialTheme.typography.bodySmall,
35 | modifier = Modifier.align(Alignment.CenterVertically)
36 | )
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/commons/VignetteImage.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.commons
2 |
3 | import androidx.compose.foundation.ExperimentalFoundationApi
4 | import androidx.compose.foundation.combinedClickable
5 | import androidx.compose.foundation.layout.Box
6 | import androidx.compose.foundation.layout.fillMaxSize
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.Modifier
9 | import androidx.compose.ui.draw.drawWithContent
10 | import androidx.compose.ui.graphics.BlendMode
11 | import androidx.compose.ui.graphics.Brush
12 | import androidx.compose.ui.graphics.Color
13 | import androidx.compose.ui.graphics.ColorFilter
14 | import androidx.compose.ui.layout.ContentScale
15 | import me.saket.telephoto.zoomable.glide.ZoomableGlideImage
16 |
17 | @OptIn(ExperimentalFoundationApi::class)
18 | @Composable
19 | fun VignetteImage(
20 | model: Any,
21 | contentDescription: String?,
22 | modifier: Modifier = Modifier,
23 | contentScale: ContentScale = ContentScale.Crop,
24 | colorFilter: ColorFilter? = null,
25 | onClick: () -> Unit = {},
26 | onLongClick: () -> Unit = {}
27 | ) {
28 | Box(
29 | modifier = modifier
30 | .fillMaxSize()
31 | .drawWithContent {
32 | drawContent()
33 | drawRect(
34 | brush = Brush.radialGradient(
35 | colors = listOf(Color.Transparent, Color.Black),
36 | center = center,
37 | radius = size.minDimension / 2
38 | ),
39 | blendMode = BlendMode.Multiply
40 | )
41 | }
42 | .combinedClickable(
43 | onClick = onClick,
44 | onLongClick = onLongClick
45 | )
46 | ) {
47 | ZoomableGlideImage(
48 | model = model,
49 | contentDescription = contentDescription,
50 | modifier = Modifier.fillMaxSize(),
51 | contentScale = contentScale,
52 | colorFilter = colorFilter
53 | ) {
54 | it
55 | .disallowHardwareConfig()
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/constants/DialogConstants.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.constants
2 |
3 | import androidx.compose.ui.unit.sp
4 |
5 | val DIALOG_TITLE_FONT_SIZE = 18.sp
6 | val DIALOG_OPTION_FONT_SIZE = 16.sp
7 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/common/PleaseWaitDialog.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.common
2 |
3 | import androidx.compose.foundation.layout.Row
4 | import androidx.compose.foundation.layout.Spacer
5 | import androidx.compose.foundation.layout.padding
6 | import androidx.compose.foundation.layout.width
7 | import androidx.compose.material3.AlertDialog
8 | import androidx.compose.material3.CircularProgressIndicator
9 | import androidx.compose.material3.MaterialTheme
10 | import androidx.compose.material3.Text
11 | import androidx.compose.runtime.Composable
12 | import androidx.compose.ui.Modifier
13 | import androidx.compose.ui.res.stringResource
14 | import androidx.compose.ui.unit.dp
15 | import androidx.compose.ui.window.DialogProperties
16 | import app.simple.peri.R
17 |
18 | @Composable
19 | fun PleaseWaitDialog(stateText: String = stringResource(id = R.string.please_wait), onDismissRequest: () -> Unit) {
20 | AlertDialog(
21 | onDismissRequest = { onDismissRequest() },
22 | title = { },
23 | text = {
24 | Row(
25 | modifier = Modifier.padding(top = 8.dp),
26 | verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
27 | ) {
28 | CircularProgressIndicator(
29 | strokeWidth = 6.dp,
30 | color = MaterialTheme.colorScheme.primary
31 | )
32 | Spacer(modifier = Modifier.width(16.dp))
33 | Text(stateText)
34 | }
35 | },
36 | confirmButton = {
37 |
38 | },
39 | dismissButton = {
40 |
41 | },
42 | properties = DialogProperties(
43 | dismissOnBackPress = false,
44 | dismissOnClickOutside = false
45 | )
46 | )
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/common/ShowWarningDialog.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.common
2 |
3 | import androidx.compose.material3.AlertDialog
4 | import androidx.compose.material3.Button
5 | import androidx.compose.material3.Text
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.platform.LocalContext
8 |
9 | @Composable
10 | fun ShowWarningDialog(title: String, warning: String, onDismiss: () -> Unit) {
11 | val context = LocalContext.current
12 |
13 | AlertDialog(
14 | onDismissRequest = onDismiss,
15 | title = {
16 | Text(text = title)
17 | },
18 | text = {
19 | Text(text = warning)
20 | },
21 | confirmButton = {
22 | Button(
23 | onClick = onDismiss
24 | ) {
25 | Text(text = context.getString(android.R.string.ok))
26 | }
27 | }
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/common/SureDialog.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.common
2 |
3 | import androidx.compose.foundation.layout.Column
4 | import androidx.compose.material3.AlertDialog
5 | import androidx.compose.material3.Button
6 | import androidx.compose.material3.MaterialTheme
7 | import androidx.compose.material3.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.ui.res.stringResource
10 | import androidx.compose.ui.unit.sp
11 | import app.simple.peri.R
12 |
13 | @Composable
14 | fun SureDialog(
15 | title: String = stringResource(R.string.delete),
16 | message: String,
17 | onSure: () -> Unit,
18 | onDismiss: () -> Unit
19 | ) {
20 | AlertDialog(
21 | onDismissRequest = { onDismiss() },
22 | title = {
23 | Text(text = title)
24 | },
25 | text = {
26 | Column {
27 | Text(
28 | text = message,
29 | fontSize = 14.sp,
30 | color = MaterialTheme.colorScheme.secondary,
31 | lineHeight = 16.sp
32 | )
33 | }
34 | },
35 | confirmButton = {
36 | Button(onClick = { onSure() }) {
37 | Text(stringResource(id = R.string.yes))
38 | }
39 | },
40 | dismissButton = {
41 | Button(onClick = { onDismiss() }) {
42 | Text(stringResource(id = R.string.no))
43 | }
44 | },
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/livewallpapers/LiveWallpapersMenu.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.livewallpapers
2 |
3 | import androidx.compose.foundation.layout.Column
4 | import androidx.compose.foundation.layout.fillMaxWidth
5 | import androidx.compose.material3.AlertDialog
6 | import androidx.compose.material3.Button
7 | import androidx.compose.material3.ButtonDefaults
8 | import androidx.compose.material3.MaterialTheme
9 | import androidx.compose.material3.Text
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.graphics.Color
13 | import androidx.compose.ui.res.stringResource
14 | import androidx.compose.ui.text.font.FontWeight
15 | import androidx.compose.ui.text.style.TextAlign
16 | import app.simple.peri.R
17 | import app.simple.peri.models.LiveWallpaperInfo
18 | import app.simple.peri.ui.constants.DIALOG_OPTION_FONT_SIZE
19 |
20 | @Composable
21 | fun LiveWallpapersMenu(liveWallpaperInfo: LiveWallpaperInfo? = null, onDismiss: () -> Unit, onOptionSelected: (String) -> Unit) {
22 | val options = listOf(
23 | stringResource(R.string.delete)
24 | )
25 |
26 | AlertDialog(
27 | title = {
28 | Text(
29 | text = liveWallpaperInfo?.name ?: "",
30 | )
31 | },
32 | onDismissRequest = { onDismiss() },
33 | text = {
34 | Column {
35 | options.forEach { option ->
36 | Button(
37 | onClick = {
38 | onOptionSelected(option)
39 | onDismiss()
40 | },
41 | colors = ButtonDefaults.buttonColors(
42 | containerColor = Color.Transparent,
43 | contentColor = MaterialTheme.colorScheme.onSurface
44 | ),
45 | modifier = Modifier.fillMaxWidth()
46 | ) {
47 | Text(
48 | text = option,
49 | color = MaterialTheme.colorScheme.onSurface,
50 | modifier = Modifier.fillMaxWidth(),
51 | textAlign = TextAlign.Center,
52 | fontWeight = FontWeight.Bold,
53 | fontSize = DIALOG_OPTION_FONT_SIZE
54 | )
55 | }
56 | }
57 | }
58 | },
59 | confirmButton = {
60 | Button(
61 | onClick = {
62 | onDismiss()
63 | }
64 | ) {
65 | Text(text = stringResource(R.string.close))
66 | }
67 | },
68 | )
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/settings/ShowInureAppManagerDialog.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.settings
2 |
3 | import android.content.Intent
4 | import androidx.compose.foundation.layout.Column
5 | import androidx.compose.foundation.layout.fillMaxWidth
6 | import androidx.compose.material3.AlertDialog
7 | import androidx.compose.material3.Button
8 | import androidx.compose.material3.Text
9 | import androidx.compose.runtime.Composable
10 | import androidx.compose.ui.platform.LocalContext
11 | import androidx.compose.ui.res.stringResource
12 | import androidx.compose.ui.window.DialogProperties
13 | import androidx.core.net.toUri
14 | import app.simple.peri.R
15 |
16 | private const val INURE_GITHUB_URL = "https://github.com/Hamza417/Inure"
17 | private const val INURE_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=app.simple.inure.play"
18 | private const val INURE_F_DROID_URL = "https://f-droid.org/packages/app.simple.inure"
19 | private const val INURE_IZZY_URL = "https://apt.izzysoft.de/fdroid/index/apk/app.simple.inure/"
20 |
21 | @Composable
22 | fun ShowInureAppManagerDialog(onDismiss: () -> Unit) {
23 | val context = LocalContext.current
24 | val list = listOf("GitHub", "Play Store", "F-Droid", "IzzyOnDroid")
25 |
26 | AlertDialog(
27 | onDismissRequest = {
28 | onDismiss()
29 | },
30 | title = { Text(text = stringResource(id = R.string.inure_app_manager)) },
31 | text = {
32 | Column(
33 | modifier = androidx.compose.ui.Modifier.fillMaxWidth(),
34 | horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally
35 | ) {
36 | list.forEachIndexed { index, item ->
37 | Button(
38 | modifier = androidx.compose.ui.Modifier.fillMaxWidth(),
39 | onClick = {
40 | val url = when (index) {
41 | 0 -> INURE_GITHUB_URL
42 | 1 -> INURE_PLAY_STORE_URL
43 | 2 -> INURE_F_DROID_URL
44 | 3 -> INURE_IZZY_URL
45 | else -> INURE_GITHUB_URL
46 | }
47 | val intent = Intent(Intent.ACTION_VIEW, url.toUri())
48 | context.startActivity(intent)
49 | }) {
50 | Text(text = item)
51 | }
52 | }
53 | }
54 | },
55 | confirmButton = {
56 | Button(
57 | onClick = {
58 | onDismiss()
59 | }
60 | ) {
61 | Text(text = stringResource(id = R.string.close))
62 | }
63 | },
64 | properties = DialogProperties(dismissOnClickOutside = true)
65 | )
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/dialogs/settings/ShowPositionalDialog.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.dialogs.settings
2 |
3 | import android.content.Intent
4 | import android.net.Uri
5 | import androidx.compose.foundation.layout.Column
6 | import androidx.compose.foundation.layout.fillMaxWidth
7 | import androidx.compose.material3.AlertDialog
8 | import androidx.compose.material3.Button
9 | import androidx.compose.material3.Text
10 | import androidx.compose.runtime.Composable
11 | import androidx.compose.ui.platform.LocalContext
12 | import androidx.compose.ui.res.stringResource
13 | import androidx.compose.ui.window.DialogProperties
14 | import app.simple.peri.R
15 |
16 | private const val POSITIONAL_GITHUB_URL = "https://github.com/Hamza417/Positional"
17 | private const val POSITIONAL_PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=app.simple.positional"
18 |
19 | @Composable
20 | fun ShowPositionalDialog(onDismiss: () -> Unit) {
21 | val context = LocalContext.current
22 | val list = listOf("GitHub", "Play Store")
23 |
24 | AlertDialog(
25 | onDismissRequest = { onDismiss() },
26 | title = { Text(text = stringResource(id = R.string.positional)) },
27 | text = {
28 | Column(
29 | modifier = androidx.compose.ui.Modifier.fillMaxWidth(),
30 | horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally
31 | ) {
32 | list.forEachIndexed { index, item ->
33 | Button(
34 | modifier = androidx.compose.ui.Modifier.fillMaxWidth(),
35 | onClick = {
36 | val url = when (index) {
37 | 0 -> POSITIONAL_GITHUB_URL
38 | 1 -> POSITIONAL_PLAY_STORE_URL
39 | else -> POSITIONAL_GITHUB_URL
40 | }
41 | val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
42 | context.startActivity(intent)
43 | onDismiss()
44 | }) {
45 | Text(text = item)
46 | }
47 | }
48 | }
49 | },
50 | confirmButton = {
51 | Button(
52 | onClick = {
53 | onDismiss()
54 | }
55 | ) {
56 | Text(text = stringResource(id = R.string.close))
57 | }
58 | },
59 | properties = DialogProperties(dismissOnClickOutside = true)
60 | )
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/nav/Routes.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.nav
2 |
3 | object Routes {
4 | const val SETUP = "setup"
5 | const val HOME = "home"
6 | const val LIST = "list"
7 | const val WALLPAPER = "wallpaper"
8 | const val SETTINGS = "settings"
9 | const val WALLPAPERS_LIST = "wallpapers"
10 | const val AUTO_WALLPAPER = "auto_wallpaper"
11 | const val LIVE_AUTO_WALLPAPER = "live_auto_wallpaper"
12 | const val TAGS = "tags"
13 | const val TAGGED_WALLPAPERS = "tagged_wallpapers"
14 | const val FOLDERS = "folders"
15 | const val LIVE_WALLPAPERS = "live_wallpapers"
16 |
17 | const val WALLPAPER_ARG = "wallpaper_arg"
18 | const val FOLDER_ARG = "folder_arg"
19 | const val TAG_ARG = "tag_arg"
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/settings/SkipColumn.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.settings
2 |
3 | import DescriptionPreference
4 | import SecondaryHeader
5 | import SwitchPreference
6 | import androidx.compose.runtime.Composable
7 | import androidx.compose.ui.res.stringResource
8 | import androidx.compose.ui.unit.dp
9 | import app.simple.peri.R
10 | import app.simple.peri.preferences.MainComposePreferences
11 |
12 | @Composable
13 | fun SkipColumn() {
14 | SecondaryHeader(title = stringResource(R.string.skip))
15 | DescriptionPreference(description = stringResource(R.string.skip_when_condition_summary))
16 |
17 | SwitchPreference(
18 | title = stringResource(R.string.skip_when_portrait),
19 | checked = MainComposePreferences.getDontChangeWhenPortrait(),
20 | topPadding = 4.dp
21 | ) {
22 | MainComposePreferences.setDontChangeWhenPortrait(it)
23 | }
24 |
25 | SwitchPreference(
26 | title = stringResource(R.string.skip_when_landscape),
27 | checked = MainComposePreferences.getDontChangeWhenLandscape(),
28 | topPadding = 4.dp
29 | ) {
30 | MainComposePreferences.setDontChangeWhenLandscape(it)
31 | }
32 |
33 | SwitchPreference(
34 | title = stringResource(R.string.skip_when_low_battery),
35 | checked = MainComposePreferences.getDontChangeWhenLowBattery(),
36 | topPadding = 4.dp
37 | ) {
38 | MainComposePreferences.setDontChangeWhenLowBattery(it)
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple80 = Color(0xFFD0BCFF)
6 | val PurpleGrey80 = Color(0xFFCCC2DC)
7 | val Pink80 = Color(0xFFEFB8C8)
8 |
9 | val Purple40 = Color(0xFF6650a4)
10 | val PurpleGrey40 = Color(0xFF625b71)
11 | val Pink40 = Color(0xFF7D5260)
12 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/ui/theme/Typography.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.ui.theme
2 |
3 | import androidx.compose.material3.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | bodyLarge = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp,
15 | lineHeight = 24.sp,
16 | letterSpacing = 0.5.sp
17 | ),
18 | bodySmall = TextStyle(
19 | fontFamily = FontFamily.Default,
20 | fontWeight = FontWeight.Normal,
21 | fontSize = 14.sp,
22 | lineHeight = 20.sp,
23 | letterSpacing = 0.25.sp
24 | ),
25 | )
26 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/BatteryUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.content.Context
4 | import android.os.BatteryManager
5 |
6 | object BatteryUtils {
7 |
8 | private const val LOW_BATTERY_THRESHOLD = 20
9 |
10 | fun Context.getBatteryPercentage(): Int {
11 | val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
12 | return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
13 | }
14 |
15 | fun Context.isLowBattery(): Boolean {
16 | return getBatteryPercentage() <= LOW_BATTERY_THRESHOLD
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/CommonUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import kotlinx.coroutines.flow.MutableStateFlow
4 |
5 | object CommonUtils {
6 |
7 | /**
8 | * Execute a block of code with a boolean scope flag. What it does is set the flag to true
9 | * before executing the block, and then set it back to false after the block is done.
10 | */
11 | inline fun withBooleanScope(scopeFlag: MutableStateFlow, block: () -> T): T {
12 | scopeFlag.value = true
13 | return try {
14 | block()
15 | } finally {
16 | scopeFlag.value = false
17 | }
18 | }
19 |
20 | fun Float.toSeconds(): Float {
21 | return this / 1000f
22 | }
23 |
24 | fun Long.toSeconds(): Long {
25 | return this / 1000
26 | }
27 |
28 | fun Int.toSeconds(): Int {
29 | return this / 1000
30 | }
31 |
32 | fun Double.toSeconds(): Double {
33 | return this / 1000
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/ConditionUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | @Suppress("unused")
4 | object ConditionUtils {
5 | /**
6 | * Quickly performs a null safety check
7 | * of a potential null object that has
8 | * no way to initialize but to throw an
9 | * exception. This approach is unsafe
10 | * and should not be used with conditional
11 | * statements
12 | *
13 | * Requires casting to the original object
14 | *
15 | * @throws UninitializedPropertyAccessException
16 | * @return [Any]
17 | */
18 | fun Any?.asNotNull(): Any {
19 | return this ?: throw UninitializedPropertyAccessException()
20 | }
21 |
22 | /**
23 | * Check if an object is null
24 | *
25 | * @return true if null
26 | */
27 | fun Any?.isNull(): Boolean {
28 | return this == null
29 | }
30 |
31 | /**
32 | * Check if an object is null
33 | *
34 | * @return true if not null
35 | */
36 | fun Any?.isNotNull(): Boolean {
37 | return this != null
38 | }
39 |
40 | /**
41 | * Checks if a number is 0
42 | *
43 | * @return [Boolean]
44 | */
45 | fun Number.isZero(): Boolean {
46 | return this == 0
47 | }
48 |
49 | /**
50 | * Checks if a number is not 0
51 | *
52 | * @return [Boolean]
53 | */
54 | fun Number.isNotZero(): Boolean {
55 | return this != 0
56 | }
57 |
58 | /**
59 | * Check is a number is equal to another number
60 | *
61 | * @return [Boolean]
62 | */
63 | fun Number.isEqualTo(number: Number): Boolean {
64 | return this == number
65 | }
66 |
67 | /**
68 | * Inverts the current boolean
69 | *
70 | * @return [Boolean]
71 | */
72 | fun Boolean.invert(): Boolean {
73 | return !this
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/DoubleTapDetector.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.content.Context
4 | import android.view.GestureDetector
5 | import android.view.MotionEvent
6 |
7 | class DoubleTapDetector(
8 | context: Context,
9 | private val onDoubleTapListener: (MotionEvent) -> Unit
10 | ) {
11 | private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
12 | override fun onDoubleTap(e: MotionEvent): Boolean {
13 | onDoubleTapListener(e)
14 | return true
15 | }
16 | })
17 |
18 | fun onTouchEvent(event: MotionEvent) {
19 | gestureDetector.onTouchEvent(event)
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/ListUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | object ListUtils {
4 | fun List.deepEquals(other: List) =
5 | size == other.size && asSequence()
6 | .mapIndexed { index, element -> element == other[index] }
7 | .all { it }
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/ParcelUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.content.Intent
4 | import android.os.Build.VERSION.SDK_INT
5 | import android.os.Bundle
6 | import android.os.Parcelable
7 |
8 | @Suppress("unused")
9 | object ParcelUtils {
10 | inline fun Intent.parcelable(key: String): T? = when {
11 | SDK_INT >= 33 -> getParcelableExtra(key, T::class.java)
12 | else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T
13 | }
14 |
15 | inline fun Bundle.parcelable(key: String): T? = when {
16 | SDK_INT >= 33 -> getParcelable(key, T::class.java)
17 | else -> @Suppress("DEPRECATION") getParcelable(key) as? T
18 | }
19 |
20 | inline fun Bundle.serializable(key: String): T? = when {
21 | SDK_INT >= 33 -> getSerializable(key, T::class.java)
22 | else -> @Suppress("DEPRECATION") getSerializable(key) as? T
23 | }
24 |
25 | inline fun Bundle.parcelable(key: String, default: T): T = when {
26 | SDK_INT >= 33 -> getParcelable(key, T::class.java) ?: default
27 | else -> @Suppress("DEPRECATION") getParcelable(key) as? T ?: default
28 | }
29 |
30 | inline fun Bundle.parcelable(key: String, default: () -> T): T = when {
31 | SDK_INT >= 33 -> getParcelable(key, T::class.java) ?: default()
32 | else -> @Suppress("DEPRECATION") getParcelable(key) as? T ?: default()
33 | }
34 |
35 | inline fun Bundle.parcelableArrayList(key: String): ArrayList? = when {
36 | SDK_INT >= 33 -> getParcelableArrayList(key, T::class.java)
37 | else -> @Suppress("DEPRECATION") getParcelableArrayList(key)
38 | }
39 |
40 | inline fun Intent.parcelableArrayList(key: String): ArrayList? = when {
41 | SDK_INT >= 33 -> getParcelableArrayListExtra(key, T::class.java)
42 | else -> @Suppress("DEPRECATION") getParcelableArrayListExtra(key)
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/PermissionUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.Manifest
4 | import android.annotation.SuppressLint
5 | import android.content.Context
6 | import android.content.Intent
7 | import android.content.pm.PackageManager
8 | import android.net.Uri
9 | import android.os.Build
10 | import android.os.Environment
11 | import android.os.PowerManager
12 | import android.provider.Settings
13 | import androidx.annotation.RequiresApi
14 | import androidx.core.app.NotificationManagerCompat
15 | import androidx.core.content.ContextCompat
16 |
17 | object PermissionUtils {
18 |
19 | /**
20 | * return true if in App's Battery settings "Not optimized" and false if "Optimizing battery use"
21 | */
22 | fun Context.isBatteryOptimizationDisabled(): Boolean {
23 | return (getSystemService(Context.POWER_SERVICE) as PowerManager)
24 | .isIgnoringBatteryOptimizations(packageName)
25 | }
26 |
27 | @SuppressLint("BatteryLife")
28 | fun Context.requestIgnoreBatteryOptimizations() {
29 | val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
30 | if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
31 | val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply {
32 | data = Uri.parse("package:$packageName")
33 | }
34 | startActivity(intent)
35 | }
36 | }
37 |
38 | fun checkStoragePermission(context: Context): Boolean {
39 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
40 | Environment.isExternalStorageManager()
41 | } else {
42 | ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
43 | }
44 | }
45 |
46 | @RequiresApi(Build.VERSION_CODES.TIRAMISU)
47 | fun checkMediaImagesPermission(context: Context): Boolean {
48 | return ContextCompat.checkSelfPermission(context, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED
49 | }
50 |
51 | @RequiresApi(Build.VERSION_CODES.TIRAMISU)
52 | fun checkNotificationPermission(context: Context): Boolean {
53 | return NotificationManagerCompat.from(context).areNotificationsEnabled()
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/ProcessUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.app.ActivityManager
4 | import android.content.Context
5 | import kotlinx.coroutines.CancellationException
6 | import kotlinx.coroutines.Job
7 |
8 | object ProcessUtils {
9 | fun MutableSet.cancelAll(cause: String) {
10 | forEach { it.cancel(CancellationException(cause)) }
11 | clear()
12 | }
13 |
14 | @Suppress("DEPRECATION")
15 | fun Context.isServiceRunning(serviceClass: Class<*>): Boolean {
16 | val activityManager = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
17 |
18 | /**
19 | * "As of Build. VERSION_CODES. O, this method is no longer available
20 | * to third party applications. For backwards compatibility, it will still
21 | * return the caller's own services."
22 | *
23 | * If we are querying my app's services, this method will work just fine.
24 | */
25 | val services = activityManager.getRunningServices(Int.MAX_VALUE)
26 | for (service in services) {
27 | if (serviceClass.name == service.service.className) {
28 | return true
29 | }
30 | }
31 |
32 | return false
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/ServiceUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import android.app.ActivityManager
4 | import android.content.Context
5 | import app.simple.peri.services.LiveAutoWallpaperService
6 |
7 | object ServiceUtils {
8 | fun isWallpaperServiceRunning(context: Context): Boolean {
9 | val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
10 | @Suppress("DEPRECATION") val services = manager.getRunningServices(Integer.MAX_VALUE)
11 | return services.any { it.service.className == LiveAutoWallpaperService::class.java.name }
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/StringUtils.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | object StringUtils {
4 |
5 | fun String?.endsWithAny(vararg strings: String): Boolean {
6 | strings.forEach {
7 | if (this?.endsWith(it) == true) {
8 | return true
9 | }
10 | }
11 | return false
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/utils/WallpaperSort.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.utils
2 |
3 | import app.simple.peri.models.Wallpaper
4 | import app.simple.peri.preferences.MainPreferences
5 |
6 | object WallpaperSort {
7 |
8 | const val NAME = "name"
9 | const val DATE = "date"
10 | const val SIZE = "size"
11 | const val WIDTH = "width"
12 | const val HEIGHT = "height"
13 |
14 | const val ASC = "asc"
15 | const val DESC = "desc"
16 |
17 | fun ArrayList.getSortedList() {
18 | when (MainPreferences.getSort()) {
19 | NAME -> sortByName()
20 | DATE -> sortByDate()
21 | SIZE -> sortBySize()
22 | WIDTH -> sortByWidth()
23 | HEIGHT -> sortByHeight()
24 | }
25 | }
26 |
27 | fun List.getSortedList(): List {
28 | val sortedList = ArrayList(this) // Copy the list
29 | sortedList.getSortedList()
30 | return sortedList
31 | }
32 |
33 | private fun ArrayList.sortByName() {
34 | if (isOrderAsc()) {
35 | sortBy { it.name }
36 | } else {
37 | sortByDescending { it.name }
38 | }
39 | }
40 |
41 | private fun ArrayList.sortByDate() {
42 | if (isOrderAsc()) {
43 | sortBy { it.dateModified }
44 | } else {
45 | sortByDescending { it.dateModified }
46 | }
47 | }
48 |
49 | private fun ArrayList.sortBySize() {
50 | if (isOrderAsc()) {
51 | sortBy { it.size }
52 | } else {
53 | sortByDescending { it.size }
54 | }
55 | }
56 |
57 | private fun ArrayList.sortByWidth() {
58 | if (isOrderAsc()) {
59 | sortBy { it.width }
60 | } else {
61 | sortByDescending { it.width }
62 | }
63 | }
64 |
65 | private fun ArrayList.sortByHeight() {
66 | if (isOrderAsc()) {
67 | sortBy { it.height }
68 | } else {
69 | sortByDescending { it.height }
70 | }
71 | }
72 |
73 | private fun isOrderAsc(): Boolean {
74 | return MainPreferences.getOrder() == ASC
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/viewmodels/EffectsViewModel.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.viewmodels
2 |
3 | import android.app.Application
4 | import androidx.lifecycle.AndroidViewModel
5 | import androidx.lifecycle.LiveData
6 | import androidx.lifecycle.MutableLiveData
7 | import androidx.lifecycle.viewModelScope
8 | import app.simple.peri.database.instances.EffectsDatabase
9 | import app.simple.peri.models.Effect
10 | import kotlinx.coroutines.Dispatchers
11 | import kotlinx.coroutines.launch
12 | import kotlinx.coroutines.withContext
13 |
14 | class EffectsViewModel(application: Application) : AndroidViewModel(application) {
15 |
16 | private val effects: MutableLiveData> by lazy {
17 | MutableLiveData>().also {
18 | viewModelScope.launch(Dispatchers.IO) {
19 | val effectsDatabase = EffectsDatabase.getInstance(application)!!
20 | it.postValue(effectsDatabase.effectsDao().getAllEffects())
21 | }
22 | }
23 | }
24 |
25 | fun getEffects(): LiveData> {
26 | return effects
27 | }
28 |
29 | fun deleteEffect(effect: Effect, onDeleted: () -> Unit) {
30 | viewModelScope.launch(Dispatchers.IO) {
31 | val effectsDatabase = EffectsDatabase.getInstance(getApplication())!!
32 | effectsDatabase.effectsDao().deleteEffect(effect)
33 | effects.postValue(effectsDatabase.effectsDao().getAllEffects())
34 |
35 | withContext(Dispatchers.Main) {
36 | onDeleted()
37 | }
38 | }
39 | }
40 |
41 | override fun onCleared() {
42 | super.onCleared()
43 | EffectsDatabase.destroy()
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/viewmodels/StateViewModel.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.viewmodels
2 |
3 | import android.app.Application
4 | import androidx.compose.runtime.getValue
5 | import androidx.compose.runtime.mutableFloatStateOf
6 | import androidx.compose.runtime.mutableStateOf
7 | import androidx.compose.runtime.setValue
8 | import androidx.lifecycle.AndroidViewModel
9 | import androidx.lifecycle.viewModelScope
10 | import app.simple.peri.database.instances.EffectsDatabase
11 | import app.simple.peri.models.Effect
12 | import app.simple.peri.models.Folder
13 | import app.simple.peri.models.Tag
14 | import app.simple.peri.models.Wallpaper
15 | import kotlinx.coroutines.Dispatchers
16 | import kotlinx.coroutines.launch
17 | import kotlinx.coroutines.withContext
18 |
19 | class StateViewModel(application: Application) : AndroidViewModel(application) {
20 |
21 | var wallpaper by mutableStateOf(null)
22 | var tag by mutableStateOf(null)
23 | var folder by mutableStateOf(null)
24 | var blurValue by mutableFloatStateOf(0f) // 0F..25F
25 | var brightnessValue by mutableFloatStateOf(0f) // -255F..255F
26 | var contrastValue by mutableFloatStateOf(1f) // 0F..10F
27 | var saturationValue by mutableFloatStateOf(1f) // 0F..2F
28 | var hueValueRed by mutableFloatStateOf(0f) // 0F..360F
29 | var hueValueGreen by mutableFloatStateOf(0f) // 0F..360F
30 | var hueValueBlue by mutableFloatStateOf(0f) // 0F..360F
31 | var scaleValueRed by mutableFloatStateOf(1f) // 0F..1F
32 | var scaleValueGreen by mutableFloatStateOf(1f) // 0F..1F
33 | var scaleValueBlue by mutableFloatStateOf(1f) // 0F..1F
34 |
35 | fun saveEffectInDatabase(effect: Effect, onEffectSaved: () -> Unit) {
36 | viewModelScope.launch(Dispatchers.IO) {
37 | val effectDao = EffectsDatabase.getInstance(getApplication())?.effectsDao()
38 | effectDao?.insertEffect(effect)
39 |
40 | withContext(Dispatchers.Main) {
41 | onEffectSaved()
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/widgets/NextWallpaper.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.widgets
2 |
3 | import android.app.PendingIntent
4 | import android.appwidget.AppWidgetManager
5 | import android.appwidget.AppWidgetProvider
6 | import android.content.Context
7 | import android.content.Intent
8 | import android.util.Log
9 | import android.widget.RemoteViews
10 | import app.simple.peri.R
11 | import app.simple.peri.services.AutoWallpaperService
12 |
13 | open class NextWallpaper : AppWidgetProvider() {
14 |
15 | override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) {
16 | super.onUpdate(context, appWidgetManager, appWidgetIds)
17 | Log.d(TAG, "onUpdate")
18 |
19 | // Loop through all widget instances
20 | appWidgetIds?.forEach { appWidgetId ->
21 | val intent = Intent(context, AutoWallpaperService::class.java)
22 | intent.action = AutoWallpaperService.ACTION_NEXT_WALLPAPER
23 | val pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
24 |
25 | // Get the layout for the App Widget and attach an on-click listener to the button
26 | val views = RemoteViews(context?.packageName, getLayoutID())
27 | views.setOnClickPendingIntent(getButtonID(), pendingIntent)
28 |
29 | // Log a message when the widget is clicked
30 | Log.d(TAG, "Widget clicked")
31 |
32 | // Tell the AppWidgetManager to perform an update on the current App Widget
33 | appWidgetManager?.updateAppWidget(appWidgetId, views)
34 | }
35 | }
36 |
37 | open fun getLayoutID(): Int {
38 | return R.layout.widget_next_wallpaper
39 | }
40 |
41 | open fun getButtonID(): Int {
42 | return R.id.widget_next_wallpaper
43 | }
44 |
45 | companion object {
46 | private const val TAG = "NextWallpaperWidget"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/widgets/NextWallpaperWidget.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.widgets
2 |
3 | import app.simple.peri.R
4 |
5 | class NextWallpaperWidget : NextWallpaper() {
6 | override fun getLayoutID(): Int {
7 | return R.layout.widget_next_wallpaper
8 | }
9 |
10 | override fun getButtonID(): Int {
11 | return R.id.widget_next_wallpaper
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/app/simple/peri/widgets/NextWallpaperWidgetTransparent.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri.widgets
2 |
3 | import app.simple.peri.R
4 |
5 | class NextWallpaperWidgetTransparent : NextWallpaper() {
6 | override fun getLayoutID(): Int {
7 | return R.layout.widget_next_wallpaper_transparent
8 | }
9 |
10 | override fun getButtonID(): Int {
11 | return R.id.widget_next_wallpaper
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/inure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/drawable-nodpi/inure.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-nodpi/positional.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/drawable-nodpi/positional.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_copy_all.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_fast_forward.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_next_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_peristyle.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_share.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/swap_vert.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_next_wallpaper.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_next_wallpaper_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_next.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_next_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_next.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-hdpi/ic_next.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_next_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-hdpi/ic_next_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_next.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-mdpi/ic_next.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_next_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-mdpi/ic_next_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_next.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xhdpi/ic_next.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_next_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xhdpi/ic_next_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_next.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxhdpi/ic_next.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_next_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxhdpi/ic_next_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_next.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxxhdpi/ic_next.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_next_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/app/src/main/res/mipmap-xxxhdpi/ic_next_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_next_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/non_translatable_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Peristyle
4 | Inure App Manager
5 | Positional
6 | An elegant and beautiful premium Android app manager for both rooted and non-rooted devices and a built-in terminal, analytics panel and an independent custom theme engine, developed with purely custom APIs created for this app.
7 | An elegant and colorful location information app for Android with Compass, Clock, Level, Sun, Moon, Trail Marker and many other features.
8 | GitHub
9 | Play Store
10 | Wallpaper Manager API
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/live_auto_wallpaper.xml:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
15 |
18 |
19 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/widget_next_wallpaper.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/widget_next_wallpaper_transparent.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/app/simple/peri/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package app.simple.peri
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '8.10.1' apply false
4 | id 'com.android.library' version '8.10.1' apply false
5 | id 'org.jetbrains.kotlin.android' version '2.0.20' apply false
6 | id 'com.google.devtools.ksp' version '2.0.20-1.0.25' apply false
7 | id 'org.jetbrains.kotlin.plugin.compose' version '2.0.20' apply false
8 | }
9 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /app/src/main/res/values/strings.xml
3 | translation: /app/src/main/res/values-%android_code%/%original_file_name%
4 | translate_content: 0
5 | translate_attributes: 0
6 |
7 | - source: /fastlane/metadata/android/en-US/full_description.txt
8 | translation: /fastlane/metadata/android/%locale%/full_description.txt
9 | translate_content: 1
10 | translate_attributes: 0
11 |
12 | - source: /fastlane/metadata/android/en-US/short_description.txt
13 | translation: /fastlane/metadata/android/%locale%/short_description.txt
14 | translate_content: 1
15 | translate_attributes: 0
16 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ar-SA/full_description.txt:
--------------------------------------------------------------------------------
1 | تم إنشاء Peristyle ليكون تطبيق إدارة وتصفح خلفيات في غاية البساطة والتطور لأجهزة Android. إنه يحل مشكلة وجود الكثير من الميزات والتطبيقات الثقيلة والحصول على الحد الأدنى من دعم الخلفيات المخزنة محليًا. ماذا لو كنت ترغب/ين فقط في تطبيق يسمح لك بتصفح وتحديد الخلفيات المخزنة محليًا ويتيح لك إدارة وتعيين الخلفيات من هناك؟ إذًا Peristyle لك :)
2 |
3 | الميزات:
4 |
5 | - معمارية بسيطة، تصفح الخلفيات واستخدام إدارة الخلفيات في النظام لتعيينها كخلفية.
6 | - دعم تعدد المجلدات.
7 | - القدرة على تعيين وسوم لأي خلفية.
8 | - يمكن مسح مجلدات .nomedia، مفيدة إذا كنت ترغب/ين في الحفاظ على خلفياتك بعيدةً عن المعرض.
9 | - تطبيق فلاتر الألوان والضبابية على أي خلفية ديناميكيًا قبل التطبيق.
10 | - رسوم متحركة بسيطة ولكن جميلة مع التحسينات المناسبة.
11 | - ضغط وتقليل الصور بالمرة.
12 | - لا إعلانات ولا تعقب ولا تحليلات ولا أذونات إنترنت ولا أذونات غير ضرورية.
13 | - دعم التغيير التلقائي للخلفيات مع المجلدات والوسوم المخصصة لكل شاشة.
14 | - تغيير خلفية الشاشة باستخدام خلفيات التطبيق الحية
15 | - تحرير وتطبيق الفلاتر على الخلفيات بلا خسارة جودة آنيًا.
16 | - منتقي خلفيات حية مدمج.
17 | - دعم الوضع الداكن.
18 | - واجهة استخدام زجاجية مستندة إلى تأثيرات ضبابية وظلال كاوية آنية.
19 | - سمة ألوان Material You.
20 | - بناء قابل للنسخ بالكامل.
21 | - معمارية برمجية خالية من التحميل.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ar-SA/short_description.txt:
--------------------------------------------------------------------------------
1 | تطبيق إدارة خلفيات بسيط مع دعم آلية الخلفيات وتعدد المجلدات.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de-DE/full_description.txt:
--------------------------------------------------------------------------------
1 | Peristyle wurde als ebenso einfacher wie durchdachter Hintergrundbild-Manager und -Browser für Android entwickelt. Er löst die Problematik komplexer und überladener Apps mit mangelhafter Unterstützung für lokal gespeicherte Hintergrundbilder. Was wäre, wenn Du nur eine App brauchst, um Deine lokal gespeicherten Hintergrundbilder zu durchstöbern, auszuwählen und sie von dort zu verwalten und anzuwenden? Dann ist Peristyle das Richtige für Dich :)
2 |
3 | Merkmale:
4 |
5 | - Einfache Architektur: durchsuche Hintergrundbilder und verwende die Hintergrund-Verwaltung des Systems, um sie festzulegen.
6 | - Unterstützung unterschiedlicher Ordner.
7 | - Möglichkeit, jedem Hintergrund Tags zuzuordnen.
8 | - Kann .nomedia-Verzeichnisse durchsuchen; nützlich, um Hintergrundbilder von der Galerie fernzuhalten.
9 | - Unschärfe und Farbfilter dynamisch auf jedes Hintergrundbild anwenden, bevor es festgelegt wird.
10 | - Einfache aber schöne Animationen mit den richtigen Optimierungen.
11 | - Komprimiere oder verkleinerte Bilder ganz nebenbei.
12 | - Keine Werbung, kein Tracking, keine Analytics, kein Internet-Zugriff, keine unnötigen Berechtigungen.
13 | - Unterstützt automatische Hintergrund-Änderung mit dedizierten Ordnern und Tags für jeden Bildschirm.
14 | - Hintergrund-Änderung mittels des Live-Hintergrunds der App
15 | - Bearbeite Hintergrundbilder verlustfrei und wende Filter in Echtzeit an.
16 | - Integrierte Live-Hintergrundauswahl.
17 | - Unterstützung von Dunklem Design.
18 | - Glasmorphe Benutzeroberfläche, basierend auf Echtzeit-Unschärfeeffekten und kausalen Schatten.
19 | - Material You-Farbthema.
20 | - Vollständig reproduzierbarer Build.
21 | - Ladefreie Software-Architektur.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de-DE/short_description.txt:
--------------------------------------------------------------------------------
1 | Einfache Hintergrundverwaltungs-App mit Auto-Hintergrund- und Mehrfachordner-Unterstützung.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/107.txt:
--------------------------------------------------------------------------------
1 | - HD image viewer
2 | - Option to disable details
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/122.txt:
--------------------------------------------------------------------------------
1 | - Fixed various color filter issues
2 | - Fixed filter dialog blur not working
3 | - Added blur filter
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/123.txt:
--------------------------------------------------------------------------------
1 | - Fixed staggered grid not updating it's layout after a wallpaper is removed in dynamic spans
2 | - Fixed top elements names overlapping with status bar
3 | - Updated dynamic colors for preferences icons
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/124.txt:
--------------------------------------------------------------------------------
1 | - Fixed dynamic colors not applying
2 | - Fixed preference framework issues
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/126.txt:
--------------------------------------------------------------------------------
1 | - Added option to adjust hue
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/127.txt:
--------------------------------------------------------------------------------
1 | - Sliders should now show exact values
2 | - Removed native codes from the project
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/129.txt:
--------------------------------------------------------------------------------
1 | - Added monochrome icon support
2 | - Added Auto Wallpaper Changer
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/130.txt:
--------------------------------------------------------------------------------
1 | - Added 5, 15, and 30 intervals in auto wallpaper changer (#15)
2 | - Updated auto wallpaper cropper algorithm
3 | - Fixed various issues with auto wallpaper changer
4 | - Added crop wallpaper for auto wallpaper
5 | - Added boot completed receiver for auto wallpaper
6 | - Option to use separate wallpaper for lockscreen
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/131.txt:
--------------------------------------------------------------------------------
1 | - Fixed various issues with Auto Wallpaper
2 | - Fixed Auto Wallpaper setting pixelated wallpapers
3 | - Fixed some crashes in Auto Wallpaper framework
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/132.txt:
--------------------------------------------------------------------------------
1 | - Permissive auto wallpaper warning
2 | - Updated settings interface
3 | - Major improvements in animations framework
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/133.txt:
--------------------------------------------------------------------------------
1 | - Landscape orientation support
2 | - Fixed animations issues
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/134.txt:
--------------------------------------------------------------------------------
1 | - Added option to set un-cropped wallpaper on wallpaper screen
2 | - Switch style preferences instead of check box
3 | - Removed settings toolbar due to UI inconsistencies
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/136.txt:
--------------------------------------------------------------------------------
1 | - Added a consistent loader that refreshes wallpaper automatically
2 | - Removed swipe down to refresh
3 | - Make sure the animating view have only one animation pipeline working on it
4 | - Added multilevel subdirectory tree support
5 | - Fixed wallpaper not setting for lock screen in some devices
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/137.txt:
--------------------------------------------------------------------------------
1 | - Option to prevent setting wallpaper when device is sleeping
2 | - Added intent support to run AutoWallpaperService using other apps
3 | - Added option to specify which screen to set wallpaper to for Auto Wallpaper
4 | - Improved wallpaper service to reduce wallpaper load time
5 | - Better loading status
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/138.txt:
--------------------------------------------------------------------------------
1 | - Added toggle to switch between original and crop bounds
2 | - Fixed loader states
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/139.txt:
--------------------------------------------------------------------------------
1 | - Added option to reduce motions in the app
2 | - More info in Library Stats
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/140.txt:
--------------------------------------------------------------------------------
1 | - Added battery optimization permission
2 | - Fixed blurry wallpaper issue
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/141.txt:
--------------------------------------------------------------------------------
1 | - Disabled crop wallpaper popup for fitting images
2 | - Fixed crash when blur radius is too low
3 | - Fixed incorrect screen measurements
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/142.txt:
--------------------------------------------------------------------------------
1 | - Added Turkish translation (thanks to @mikropsoft)
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/143.txt:
--------------------------------------------------------------------------------
1 | - Added option to export edited wallpapers
2 | - Added option to edit wallpaper externally
3 | - EXIF orientation correction
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/144.txt:
--------------------------------------------------------------------------------
1 | - Added transparent next wallpaper widget
2 | - Various improvements and bug fixes
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/145.txt:
--------------------------------------------------------------------------------
1 | - Added icon for exceeding wallpapers
2 | - Removed zoom animation
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/146.txt:
--------------------------------------------------------------------------------
1 | - Add next wallpaper quick tiles
2 | - Add tweaks in settings
3 | - Add option to ignore .dot files
4 | - Add option to ignore sub-folders
5 | - Add French translations (Thanks to ppp987)
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/147.txt:
--------------------------------------------------------------------------------
1 | - Added option to set wallpapers linearly
2 | - Added realtime crash monitor
3 | - Fixes crash on enabling biometric lock
4 | - Added set as wallpaper option to set wallpaper from file managers
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/148.txt:
--------------------------------------------------------------------------------
1 | - Fixed inclusion of non-image files in the database
2 | - Added polish translations (thanks to @tama10)
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/149.txt:
--------------------------------------------------------------------------------
1 | - Added Simplified Chinese translations (thanks to @shanzhaxiaok)
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/150.txt:
--------------------------------------------------------------------------------
1 | - Added Vietnamese translations (thanks to @xeus0000)
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/151.txt:
--------------------------------------------------------------------------------
1 | - Fix multiple loading session issue
2 | - Added app Telegram group link
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/152.txt:
--------------------------------------------------------------------------------
1 | - Show system wallpaper in the main list
2 | - Allows critical permissions to be granted from Preferences screen
3 | - Polaroid design for current wallpaper card
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/153.txt:
--------------------------------------------------------------------------------
1 | - Remove round corners from polaroids
2 | - Added lock screen wallpaper in the main list
3 | - Fixed wallpaper dimensions when two spans is selected
4 | - Fixed crash while opening an image from file manager
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/154.txt:
--------------------------------------------------------------------------------
1 | - Add 3 and 7 days interval options
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/200.txt:
--------------------------------------------------------------------------------
1 | - Total UI overhaul based completely on Jetpack Compose
2 | - Added option to assign tags to wallpapers
3 | - Add direct image based shadow
4 | - MD5 Checksum based ids and prominent color based wallpaper shadows
5 | - Glassmorphic card based interface
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/201.txt:
--------------------------------------------------------------------------------
1 | - Fix blur not applying
2 | - Added header in lists with count
3 | - Fix interface overlapping status and navigation bar
4 | - Add more menus for Tags an Wallpapers
5 | - Fix loading indicators not showing
6 | - Tags thumbnails now shows according to the device aspect ratio
7 | - Various fixes and interface improvements
8 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/202.txt:
--------------------------------------------------------------------------------
1 | - Added multi folder support
2 | - Added tags and folder assignment for each screen auto wallpaper
3 | - Added sort and order in the Settings
4 | - Added selection in the main list
5 | - Various interface changes
6 | - Add Spanish and Chinese Traditional translations
7 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/203.txt:
--------------------------------------------------------------------------------
1 | - Slide and Zoom on wallpaper screen
2 | - Fixed the permission flow crashing in Android 9
3 | - Fixed no READ_MEDIA_IMAGES permission causes crash in Android 15
4 | - Fixed various issues with setup interface
5 | - Fixed Auto Wallpaper not changing wallpaper correctly
6 | - Added no lockscreen wallpaper hint for < Android 13 devices
7 | - Added basic transition animations
8 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/204.txt:
--------------------------------------------------------------------------------
1 | - Fix auto wallpaper applying wallpapers on both screens
2 | - Fix Folders screen flickering on every launch
3 | - Fix various UI issues
4 |
5 | Peristyle is stable now
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/205.txt:
--------------------------------------------------------------------------------
1 | - Fixed the looping home screen after the first setup
2 | - Added custom effects for each screen in Auto Wallpaper
3 | - Reduce animation time
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/300.txt:
--------------------------------------------------------------------------------
1 | - Added hue and saturation in wallpaper
2 | - Added hue and saturation in auto wallpaper
3 | - Added live wallpaper picker
4 | - Ability to uninstall live wallpapers
5 | - Fixed lost scroll state in wallpaper list
6 | - Long pressing buttons on home will show context tooltip
7 | - Updated home UI
8 | - Added Arabic translations
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/310.txt:
--------------------------------------------------------------------------------
1 | - Add option to add or remove nomedia from folders
2 | - Add folder visibility indicator
3 | - Hide card when click on wallpaper
4 | - Hide details card when edit dialog is opened
5 | - Added reset button in effects dialog
6 | - Main effects dialog is now semi transparent
7 | - Added option to clear image cache
8 | - Added option to remove a folder
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/320.txt:
--------------------------------------------------------------------------------
1 | - Added toggle to disable checksum calculation
2 | - Fixed various loading issues
3 | - Fixed invalid effects on final image
4 | - Fixed various UI issues on dark mode
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/330.txt:
--------------------------------------------------------------------------------
1 | - Added option to compress or reduce image on the fly
2 | - Fixed auto wallpaper effects not working properly
3 | - Added German translations
4 | - Removed telegram group links from the app
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/331.txt:
--------------------------------------------------------------------------------
1 | - Fixed crashes caused by NaN in aspect ratio
2 | - Italian translations
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/340.txt:
--------------------------------------------------------------------------------
1 | - Added a random wallpaper page on home screen
2 | - Added crossfade animation to all image thumbnails
3 | - Added a proper clear cache dialog
4 | - Added realtime database updates.
5 | - Images will load in realtime in the lists
6 | - Fix header wrapping the long text even with available space
7 | - Minor fixes
8 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/400.txt:
--------------------------------------------------------------------------------
1 | - Added option to move the header to the bottom
2 | - Added option to load original aspect ratio for thumbnails
3 | - Added option to select grid spans separately for each orientation
4 | - Added option to export edited wallpaper
5 | - Added separate RGB hue sliders
6 | - Added auto wallpaper notification with delete and send button
7 | - Added system wallpaper changed detection mechanism
8 | - Improved effects and cropping algorithms
9 | - Fixed selection menu issue
10 | - Fixed wallpaper effects state loss
11 | - Fixed loading folders taking up a long time
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/500.txt:
--------------------------------------------------------------------------------
1 | This is a destructive update meaning after update any of the previous data will be lost. If you want to keep the
2 | previous data, please do not update to this version.
3 |
4 | Read why? here: https://github.com/Hamza417/Peristyle/releases/tag/v5.0.0
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/510.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/520.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/600.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/610.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/620.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/630.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/640.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/700.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/704.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/810.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/820.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/830.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/840.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/850.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/860.txt:
--------------------------------------------------------------------------------
1 | Read the complete changelogs here: https://github.com/Hamza417/Peristyle/releases/latest
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | Peristyle is created to be extremely simple and sophisticated wallpaper manager and browser app for Android. It solves the problem of having too many features and bloated apps and having very minimal support for locally stored wallpapers. What if you just wanted an app that allows you to browse and select your own locally stored wallpapers and lets you manage and set wallpapers from there? then Peristyle is for you :)
2 |
3 | Features:
4 |
5 | - Simple architecture, browse wallpapers and use system wallpaper manager to set them as wallpaper.
6 | - Multiple folders support.
7 | - Ability to assign Tags to any wallpaper.
8 | - Can scan .nomedia directories, useful if you want to keep your wallpapers away from gallery.
9 | - Apply blur and color filters dynamically on any wallpaper before applying.
10 | - Simple yet pretty animations with proper optimizations.
11 | - Compress or reduce images on the fly.
12 | - No ads, no tracking, no analytics, no internet permissions, no unnecessary permissions.
13 | - Auto wallpaper change support with dedicated folders and tags for each screens.
14 | - Change wallpaper using app's live wallpaper
15 | - Edit and apply filters on wallpapers losslessly in realtime.
16 | - Built-in live wallpaper picker.
17 | - Dark mode support.
18 | - Glassmorphic UI based on realtime blur effects and caustic shadows.
19 | - Material You color theme.
20 | - Fully reproducible build.
21 | - Zero loading software architecture.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/04.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/05.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/06.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/07.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/08.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/09.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/10.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/11.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/fastlane/metadata/android/en-US/images/phoneScreenshots/12.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Simple wallpaper manager app with Auto Wallpaper and Multi Folder support.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title:
--------------------------------------------------------------------------------
1 | Peristyle
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/full_description.txt:
--------------------------------------------------------------------------------
1 | Peristyle zostało stworzone, by być bardzo prostą oraz łatwą w obsłudze aplikacją do porządkowania, oraz wybierania tapet na system Android. Rozwiązuje problem związany ze zbyt dużą ilością funkcji czy też programów zza dużym rozmiarem, czy także minimalnej kompatybilności z tapetami znajdującymi się na urządzeniu. Chciałbyś/łabyś aplikację, która pozwala na wybieranie oraz przeglądanie tapet prosto z pamięci urządzenia, i na zarządzanie nimi? Więc Peristyle jest strzałem w dziesiątkę. :)
2 |
3 | Funkcje:
4 |
5 | Prosta architektura do przeglądania oraz używania systemowego menadżera tapet do ustawienia ich.
6 | - Obsługa wielu folderów jednocześnie.
7 | - Dodawanie tagów do każdej tapety.
8 | - Skanowanie folderów typu .nomedia. Przydatne, jeśli chcesz, by twoje tapety nie były w galerii zdjęć na urządzeniu.
9 | - Dodawanie efektu rozmycia i filtrów kolorów do wybranej tapety tuż przed ustawieniem jej.
10 | - Proste i przyjazne dla oka zoptymalizowane animacje.
11 | - Kompresja i zmniejszanie rozmiaru pliku tapety.
12 | - Brak reklam, śledzenia, analiz oraz dostępu do internetu czy niepotrzebnych uprawnień.
13 | - Automatyczna zmiana tapety z obsługą wybranych folderów oraz tagów.
14 | - Zmień tapetę używając żywej tapety aplikacji
15 | - Edytuj i zastosuj filtry na tapetach w czasie rzeczywistym.
16 | - Wbudowany menedżer tapet animowanych.
17 | - Ciemny motyw.
18 | - Interfejs w stylu Glass, oparty na efektach rozmycia oraz cieni.
19 | - Materiał w kolorze motywu.
20 | - Budowa w pełni odtwarzalna.
21 | - Zero ładowania architektury oprogramowania.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/short_description.txt:
--------------------------------------------------------------------------------
1 | Prosty menedżer tapet z funkcją tapet animowanych oraz z obsługą kilku folderów naraz.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ru-RU/full_description.txt:
--------------------------------------------------------------------------------
1 | Peristyle создан для того, чтобы быть очень простым и продвинутым менеджером обоев для Android. Оно решает проблему слишком большой функциональности и раздутых приложений и имеет очень минимальную поддержку локально сохраненных обоев. Что если вы просто хотите приложение которое позволяет просматривать и выбирать собственные локальные обои и позволяет вам управлять и устанавливать обои оттуда? Тогда Peristyle для вас :)
2 |
3 | Возможности:
4 |
5 | - Простая архитектура, просмотр обоев и использование системного менеджера обоев для их установки в качестве обоев.
6 | - Поддержка нескольких папок.
7 | - Возможность присвоения меток любым обоям.
8 | - Может сканировать папки .nomedia, это полезно, если вы хотите сохранить свои обои из галереи.
9 | - Динамически применять размытие и цветовые фильтры на любых обоях перед применением.
10 | - Простая, но красивая анимация с надлежащей оптимизацией.
11 | - Сжатие или уменьшение изображений на лету.
12 | - Без рекламы, без отслеживания, анализа и доступа к интернету, без лишних разрешений.
13 | - Автоматическая смена обоев с помощью выделенных папок и меток для каждого экрана.
14 | - Изменить обои, используя живые обои приложения
15 | - Редактируйте и применяйте фильтры к обоям без потерь в режиме реального времени.
16 | - Встроенный выбор обоев на живую.
17 | - Поддержка тёмного режима.
18 | - Стекломорфический интерфейс, основанный на эффектах размытия в реальном времени и каустической тени.
19 | - Material You цветовая тема.
20 | - Полностью воспроизводимая сборка.
21 | - Архитектура программного обеспечения с нулевой загрузкой.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ru-RU/short_description.txt:
--------------------------------------------------------------------------------
1 | Простой менеджер обоев с поддержкой автообоев и множественных папок.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/tr-TR/full_description.txt:
--------------------------------------------------------------------------------
1 | Peristyle, Android için son derece basit ve sofistike bir duvar kağıdı yöneticisi ve tarayıcı uygulaması olarak oluşturuldu. Çok fazla özelliğe ve şişirilmiş uygulamalara sahip olma sorununu ve yerel olarak depolanan duvar kağıtları için çok az destek sunulmasını çözer. Çok fazla özelliğe ve şişirilmiş uygulamalara sahip olma sorununu ve yerel olarak depolanan duvar kağıtları için çok az destek sunulmasını çözer. Ya sadece kendi yerel olarak depolanan duvar kağıtlarınızı taramanıza ve seçmenize olanak tanıyan, bunları yönetmenize ve duvar kağıdı olarak ayarlamanıza izin veren bir uygulama isteseydiniz? O zaman Peristyle tam size göre :)
2 |
3 | Özellikler:
4 |
5 | - Basit mimari, duvar kağıtlarını tarayın ve sistem duvar kağıdı yöneticisini kullanarak bunları duvar kağıdı olarak ayarlayın.
6 | - Birden fazla klasör desteği.
7 | - Herhangi bir duvar kağıdına etiket atama yeteneği.
8 | - **.nomedia** dizinlerini tarayabilir, duvar kağıtlarınızı galeriden uzak tutmak istiyorsanız kullanışlıdır.
9 | - Uygulamadan önce herhangi bir duvar kağıdına bulanıklık ve renk filtreleri dinamik olarak uygulayın.
10 | - Uygun optimizasyonlarla basit ama hoş animasyonlar.
11 | - Görselleri anında sıkıştırma veya boyutlarını küçültme.
12 | - Reklam yok, izleme yok, analiz yok, internet izinleri yok, gereksiz izinler yok.
13 | - Özel klasörler ve her ekran için etiketlerle otomatik duvar kağıdı değiştirme desteği.
14 | - Uygulamanın canlı duvar kağıdını kullanarak duvar kağıdını değiştirin
15 | - Duvar kağıtlarını gerçek zamanlı olarak kayıpsız şekilde düzenleyin ve filtreler uygulayın.
16 | - Dahili canlı duvar kağıdı seçici.
17 | - Karanlık mod desteği.
18 | - Gerçek zamanlı bulanıklık efektleri ve ışık kırılmalarına dayalı cam benzeri kullanıcı arayüzü.
19 | - Material You renk teması.
20 | - Tamamen yeniden üretilebilir (reproducible) yapı.
21 | - Sıfır yükleme yazılım mimarisi.
22 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/tr-TR/short_description.txt:
--------------------------------------------------------------------------------
1 | Otomatik Duvar Kağıdı ve Çoklu Klasör desteğine sahip basit duvar kağıdı yöneticisi uygulaması.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/zh-CN/full_description.txt:
--------------------------------------------------------------------------------
1 | 开发Peristyle是想打造一款适用于安卓系统的极简且精致的壁纸管理与浏览应用程序。 它解决了功能过多、应用臃肿以及对本地存储壁纸的支持极少的问题。 如果您只想要一款允许您浏览并选择自己本地存储的壁纸,还能从这里管理和设置壁纸的应用程序,该怎么做呢? 那么Peristyle就非常适合你 :)
2 |
3 | 特点:
4 |
5 | - 架构简约,可浏览壁纸,使用系统壁纸管理器将其设置为壁纸 。
6 | - 支持多个文件夹。
7 | - 能够给任何壁纸分配标签。
8 | - 可以扫描.nomedia目录,如果您想让壁纸不显示在图库中,该功能很有用。
9 | - 应用壁纸前可对任何壁纸动态应用模糊和色彩滤镜。
10 | - 具有简单而精美的动画,已经过适当优化。
11 | - 即时压缩或缩小图像。
12 | - 没有广告,不会跟踪,不会分析数据,不需要连接网络,也不获取不必要的权限。
13 | - 支持自动更换壁纸,为每个屏幕设置专用文件夹和标签 。
14 | - 内置实时壁纸选取器。
15 | - 支持深色模式。
16 | - 具有基于实时模糊效果和焦散阴影的玻璃拟态用户界面。
17 | - Material You 风格主题和颜色。
18 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/zh-CN/short_description.txt:
--------------------------------------------------------------------------------
1 | 简单的壁纸管理器应用程序,支持自动切换壁纸和多文件夹功能。
2 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## For more details on how to configure your build environment visit
2 | # http://www.gradle.org/docs/current/userguide/build_environment.html
3 | #
4 | # Specifies the JVM arguments used for the daemon process.
5 | # The setting is particularly useful for tweaking memory settings.
6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
8 | #
9 | # When configured, Gradle will run in incubating parallel mode.
10 | # This option should only be used with decoupled projects. For more details, visit
11 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
12 | # org.gradle.parallel=true
13 | #Mon Oct 28 22:09:10 IST 2024
14 | android.nonTransitiveRClass=true
15 | android.useAndroidX=true
16 | kotlin.code.style=official
17 | org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" -Dfile.encoding\=UTF-8
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jul 18 21:36:32 IST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
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 |
--------------------------------------------------------------------------------
/screenshots/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/01.png
--------------------------------------------------------------------------------
/screenshots/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/02.png
--------------------------------------------------------------------------------
/screenshots/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/03.png
--------------------------------------------------------------------------------
/screenshots/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/04.png
--------------------------------------------------------------------------------
/screenshots/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/05.png
--------------------------------------------------------------------------------
/screenshots/06.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hamza417/Peristyle/66d1b4a47f2fa1c83a9855e58cf972ba18b3565a/screenshots/06.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | gradlePluginPortal()
6 | maven {
7 | url "https://jitpack.io"
8 | }
9 | }
10 | }
11 |
12 | dependencyResolutionManagement {
13 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
14 | repositories {
15 | google()
16 | mavenCentral()
17 | maven {
18 | url "https://jitpack.io"
19 | }
20 | }
21 | }
22 |
23 | rootProject.name = "Peristyle"
24 | include ':app'
25 |
--------------------------------------------------------------------------------