From c0441bff4ba174fa0fcdd332532c10e68eec6a2c Mon Sep 17 00:00:00 2001 From: ale Date: Sun, 1 Mar 2026 14:08:01 +0100 Subject: [PATCH] initial commit Signed-off-by: ale --- .github/workflows/build-release-apk.yml | 35 ++ .gitignore | 15 + LICENSE | 22 + README.md | 168 +++++++ app/.gitignore | 1 + app/build.gradle.kts | 70 +++ app/proguard-rules.pro | 21 + .../urlfinder/ExampleInstrumentedTest.kt | 24 + app/src/main/AndroidManifest.xml | 31 ++ app/src/main/assets/ic_urlfinder_logo.svg | 38 ++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 57981 bytes .../manalejandro/urlfinder/CameraScreen.kt | 340 +++++++++++++ .../manalejandro/urlfinder/CameraViewModel.kt | 237 +++++++++ .../manalejandro/urlfinder/MainActivity.kt | 32 ++ .../manalejandro/urlfinder/SettingsScreen.kt | 451 ++++++++++++++++++ .../urlfinder/UrlHistoryRepository.kt | 91 ++++ .../manalejandro/urlfinder/UrlResultsPanel.kt | 130 +++++ .../manalejandro/urlfinder/ui/theme/Color.kt | 11 + .../manalejandro/urlfinder/ui/theme/Theme.kt | 58 +++ .../manalejandro/urlfinder/ui/theme/Type.kt | 34 ++ app/src/main/res/drawable/ic_flash_off.xml | 10 + app/src/main/res/drawable/ic_flash_on.xml | 10 + app/src/main/res/drawable/ic_github.xml | 11 + .../res/drawable/ic_launcher_background.xml | 170 +++++++ .../res/drawable/ic_launcher_foreground.xml | 59 +++ app/src/main/res/drawable/ic_link.xml | 10 + .../main/res/drawable/ic_open_in_browser.xml | 10 + app/src/main/res/drawable/ic_open_source.xml | 11 + app/src/main/res/drawable/ic_qr_code.xml | 10 + app/src/main/res/drawable/ic_scan_frame.xml | 58 +++ .../main/res/drawable/ic_urlfinder_logo.xml | 63 +++ app/src/main/res/drawable/ic_warning.xml | 10 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 2674 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 4564 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 1734 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 2944 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 3654 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 6906 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 5664 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 10268 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 7618 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 13872 bytes app/src/main/res/values/colors.xml | 10 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 9 + app/src/main/res/values/themes.xml | 5 + app/src/main/res/xml/backup_rules.xml | 13 + .../main/res/xml/data_extraction_rules.xml | 19 + .../manalejandro/urlfinder/ExampleUnitTest.kt | 17 + build.gradle.kts | 5 + gradle.properties | 23 + gradle/gradle-daemon-jvm.properties | 12 + gradle/libs.versions.toml | 46 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45457 bytes gradle/wrapper/gradle-wrapper.properties | 9 + gradlew | 251 ++++++++++ gradlew.bat | 94 ++++ settings.gradle.kts | 26 + 60 files changed, 2794 insertions(+) create mode 100644 .github/workflows/build-release-apk.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/manalejandro/urlfinder/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/ic_urlfinder_logo.svg create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/com/manalejandro/urlfinder/CameraScreen.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/CameraViewModel.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/MainActivity.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/SettingsScreen.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/UrlHistoryRepository.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/UrlResultsPanel.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/ui/theme/Color.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/ui/theme/Theme.kt create mode 100644 app/src/main/java/com/manalejandro/urlfinder/ui/theme/Type.kt create mode 100644 app/src/main/res/drawable/ic_flash_off.xml create mode 100644 app/src/main/res/drawable/ic_flash_on.xml create mode 100644 app/src/main/res/drawable/ic_github.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_link.xml create mode 100644 app/src/main/res/drawable/ic_open_in_browser.xml create mode 100644 app/src/main/res/drawable/ic_open_source.xml create mode 100644 app/src/main/res/drawable/ic_qr_code.xml create mode 100644 app/src/main/res/drawable/ic_scan_frame.xml create mode 100644 app/src/main/res/drawable/ic_urlfinder_logo.xml create mode 100644 app/src/main/res/drawable/ic_warning.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/com/manalejandro/urlfinder/ExampleUnitTest.kt create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/gradle-daemon-jvm.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.github/workflows/build-release-apk.yml b/.github/workflows/build-release-apk.yml new file mode 100644 index 0000000..86b067a --- /dev/null +++ b/.github/workflows/build-release-apk.yml @@ -0,0 +1,35 @@ +name: Build & Publish APK Release + +on: + push: + tags: + - 'v*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up JDK + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Make Gradle executable + run: chmod +x ./gradlew + + - name: Build with Gradle + run: ./gradlew build + + - name: Build Debug APK + run: ./gradlew assembleDebug + + - name: Upload APK to Release + uses: softprops/action-gh-release@v1 + with: + files: app/build/outputs/apk/debug/*.apk + env: + GITHUB_TOKEN: ${{ secrets.TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b42481d --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2026 Manuel Alejandro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..046b0ff --- /dev/null +++ b/README.md @@ -0,0 +1,168 @@ +# URLFinder + +

+ URLFinder logo +

+ +

+ A free, open-source Android app that detects URLs and QR codes in real time using your device camera. +

+ +

+ Latest release + MIT License + Android + Min SDK 24 +

+ +--- + +## Features + +- πŸ“· **Real-time camera scanning** β€” live camera preview powered by CameraX +- πŸ”€ **Text URL detection** β€” recognizes URLs in any visible text using ML Kit Text Recognition +- πŸ“² **QR code scanning** β€” decodes QR codes that contain URLs with ML Kit Barcode Scanning +- πŸ”— **Clickable URLs** β€” tap any detected URL to open it in your browser (with a safety warning) +- ⚑ **Flash / torch toggle** β€” turn on the camera torch for scanning in low-light conditions +- πŸ—‚οΈ **Local history** β€” all detected URLs are saved locally and can be browsed and cleared from Settings +- ⚠️ **Safety warning dialog** β€” a confirmation dialog reminds you that URLs may be dangerous before opening +- πŸ†“ **Free & open source** β€” MIT licensed, no ads, no tracking, no analytics + +--- + +## Screenshots + +> _Coming soon_ + +--- + +## Requirements + +| | | +|---|---| +| **Android version** | 7.0 (API 24) or higher | +| **Permissions** | `CAMERA`, `INTERNET` | +| **Hardware** | Rear camera with autofocus recommended | + +--- + +## Installation + +### Download APK + +Download the latest release APK from the [Releases page](https://github.com/manalejandro/URLFinder/releases) and install it on your device. + +> You may need to enable **Install from unknown sources** in your device settings. + +### Build from source + +1. **Clone the repository** + ```bash + git clone https://github.com/manalejandro/URLFinder.git + cd URLFinder + ``` + +2. **Open in Android Studio** + - File β†’ Open β†’ select the `URLFinder` folder + - Let Gradle sync finish + +3. **Run or build** + ```bash + ./gradlew assembleDebug + # APK β†’ app/build/outputs/apk/debug/app-debug.apk + ``` + +--- + +## Architecture + +``` +MainActivity +└── CameraScreen (Jetpack Compose) + β”œβ”€β”€ CameraViewModel + β”‚ β”œβ”€β”€ CameraX (Preview + ImageAnalysis) + β”‚ β”œβ”€β”€ ML Kit Text Recognition β†’ extracts URLs from plain text + β”‚ └── ML Kit Barcode Scanner β†’ decodes QR codes + β”œβ”€β”€ UrlResultsPanel (LazyColumn of detected URLs) + └── SettingsScreen + β”œβ”€β”€ History tab (UrlHistoryRepository β€” SharedPreferences) + └── About tab (open-source info + GitHub link) +``` + +**Key design decisions:** +- Frame analysis is **throttled to 800 ms** to reduce CPU/battery usage. +- `ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST` drops frames that arrive while the previous one is still being processed. +- Both text and barcode analyzers run **concurrently** on the same frame, results are merged. +- URLs are **deduplicated** per session; the history avoids duplicate entries too. +- The history is stored as JSON in `SharedPreferences` (no external DB dependency). + +--- + +## Tech stack + +| Library | Version | Purpose | +|---|---|---| +| Kotlin | 2.0.21 | Programming language | +| Jetpack Compose (BOM) | 2024.09.00 | UI toolkit | +| Material 3 | β€” | Design system | +| CameraX | 1.4.2 | Camera access and analysis | +| ML Kit Text Recognition | 16.0.1 | URL detection in text | +| ML Kit Barcode Scanning | 17.3.0 | QR code decoding | +| Accompanist Permissions | 0.37.0 | Runtime camera permission | +| Lifecycle ViewModel Compose | 2.10.0 | State management | + +--- + +## Permissions + +| Permission | Reason | +|---|---| +| `CAMERA` | Required to capture and analyze camera frames for URLs and QR codes | +| `INTERNET` | Required to open detected URLs in the browser | + +--- + +## Contributing + +Contributions are welcome! Feel free to: + +- Open an [issue](https://github.com/manalejandro/URLFinder/issues) to report a bug or suggest a feature +- Fork the repo and submit a pull request + +Please follow the existing code style (Kotlin + Compose conventions) and add documentation to public APIs. + +--- + +## License + +``` +MIT License + +Copyright (c) 2026 Manuel Alejandro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +--- + +

+ Made with ❀️ using Kotlin, Jetpack Compose, CameraX and ML Kit
+ https://github.com/manalejandro/URLFinder +

+ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..097c463 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,70 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.compose) +} + +android { + namespace = "com.manalejandro.urlfinder" + compileSdk { + version = release(36) { + minorApiLevel = 1 + } + } + + defaultConfig { + applicationId = "com.manalejandro.urlfinder" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + buildFeatures { + compose = true + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.lifecycle.runtime.compose) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.compose.material3) + // CameraX + implementation(libs.androidx.camera.core) + implementation(libs.androidx.camera.camera2) + implementation(libs.androidx.camera.lifecycle) + implementation(libs.androidx.camera.view) + // ML Kit + implementation(libs.mlkit.text.recognition) + implementation(libs.mlkit.barcode.scanning) + // Permissions + implementation(libs.accompanist.permissions) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.compose.ui.test.junit4) + debugImplementation(libs.androidx.compose.ui.tooling) + debugImplementation(libs.androidx.compose.ui.test.manifest) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/manalejandro/urlfinder/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/manalejandro/urlfinder/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..fb37de2 --- /dev/null +++ b/app/src/androidTest/java/com/manalejandro/urlfinder/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.manalejandro.urlfinder + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.manalejandro.urlfinder", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..1b93123 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/ic_urlfinder_logo.svg b/app/src/main/assets/ic_urlfinder_logo.svg new file mode 100644 index 0000000..27e3583 --- /dev/null +++ b/app/src/main/assets/ic_urlfinder_logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..da8af943120e1cdbbe51f54ee35422a77db4bed4 GIT binary patch literal 57981 zcmb4qc{r5)`}T}|7n0p5LS&1OZAhXJB~jT`O4-9?o3ZbPHcAYsh$JbLWh{e`?2&E8 zj4kVor5Vif-g=&=@ALh=%W=Ga<>=tPulxF3%XyyH^+~opXU@wd&IJO2c+Xgzx&Q(( z0Y5T8sp5P0h}0 z>sF6Duf5kLF@2EBWJ!v2&Aa~o>$Mso{ap{QP!Ij;!n&UauJk3y8NaEn)L@IPY#u$z z<{1(=rB_q;Vm17n{p6L;!;_zB2B?l?-us|_tet(0FAa^i<ef?jwx3{Q;CBYwWeh<#f&Up3eZda;{a3M@pn_Y#|9ECfgZBQ| zhi8Bp0sP6Ubd&$jhs2kt`cgGJDOfWKW9dF4ih>Hc5cP&ydE8o=19;Sjh(qz>tu7Zw zlwQyo_%H%?7)cF!M)7i@u03ZXpm-_0FJ_QuL~Q6z8w3UTDiK{YkifpZ^j%A3egQB( zFhlZQTDbQ!9R;o0EWwBl%C62gQNeaze)h^NO|F@d(pzIU`vJ?ZUmfcYObOdaa?Yr6 zEjN&#pyMtxNwhLIe{oYk`cNx&n>L`OBD?p|VqTbU2BkVDFW))!33h{v$~bbfiFR`~ z3%1+Fg4L#f6TB@d7#qEfK5osO0r*D6LiFv!KF_#RiLtc4+!qu}W)N>Jq})Kz5B*}a zJEu0hn4QU*I|ca7p6qKxGbfFO*Ol2nDZ38>I}t)-FVqg+e9FD&QIWH!h&_W8AKO!h z{I2iE`$h0!B8@5%pp9K1W2RLRp~zdj&9!24jH!o?urE|G@28IofTOBAz8v<>6qb-V^;JhAG=hi}XDRCV28s&PFx>M+_A&yA4WOK(~_`vJ^*e~&^uzs93 z0q&qSE>Ab4la&Y^)5wZrQNFX!%WW&0D30wNNBw>#49uz64vgkgKjPMq7|DGWmbCdT=u5x^S)zC&3Rk=?0;h@|t{QWXuv2*0yA-V?`}M)4mAE5IznX^X z$fcJd9}It`Rrqv0b#C{sn~RcLqk~pC2*??UtBVAy zH?fBgO!aujUXXP=u3TN*;j2ptzx6Km6n@14f4fG`e6n~b8lAF*Q zSbm&3na3$N6}3{?!D3+dHQH@`(HSq;f@x#6H7d3|YVg9{p}7M-nr7`k$Wz~7%g=OW z8i@EynV2n4&AwU?ug3JR=PxRmyXJl+4R3xto%B`Kp68)tgcReexEM#s$(2&f(-_W; zumTJvND#|RX>jX2L6@Ak4T3jP4U2DWpXLW$nN}BBe^RO43Nfa3==cfLv`yc-8L$$y zA}#PGcWo;BR4nugsY9PdUQ7dXbw^2roH`C7J#JcmEbZwJMA46{1s^^Moz2y2n`C`W z#Bx^gwr3rmT2C}7cO2ygqB9K}3l6B0p&R9x+NcU}^90B^K61KNdspIN?+VvZ`Y}U} zo7+}^6?Dr4SB&2A9V5K!z>xc?Dx0I<%ber;J4Ro!L4|pvY)KtkOrlrQRNEy@UA_+- zW=ap`7gSzvwj{i$W6wgLJ{fS~_l0XHTpb|+SeaD=RLs@!6L`kZ5 zrMnlkPz*6Nc7HV3;H*fE+Kv7%QtbL}_esYusw`_ZR%aOFQQ90|`?5JcP>a|>D$vf{ zjik}TvGW@A!>0{MitzgZGdJ_cY@l89eYm=0C|lHf(mmo-)Izf0rQ_{L}8K^ zXT?b)4>nRIP4*Bq?7_v-Pw@@6Ecks zxa(r%m0G)u$X1VO_?qdM^ThkU1`jU5Oek9%F0bO;z7HY6+W#)RkR7Zt0whB>|JD(6 zs@%?M234cBwr%Cbwas#ymGQ!6o5OEgE3}b|;cegROYZXd7LFfmi26nH@65wLOQhL*u;0yC%XzqC*{xm9IVwZBz08r${Xw=ZnKpJq+TP0 zGeaR!>48JTr|fcCK^unUw~F=x!?&zsskamMV4`-LoR#`~UAyvry5 zGDlr6)#_F|@}XaH%Su{v7&&FSYF2g}XbAXU7ELsd=WF}mk4csOkzhWS+0!o+ zL`_AE!a*XE=cJ@LCfZQ3Sbbd%99d8`0@G{Vx~2tsk(2MFRf0NGkbVs4(w~a>D%Nt% zseub8tf=X5WOz40qT2CZBbyE(OLkSdodu~y8iucZ`A zX&?4gmaEKuiGk)xvwY|;WC!_d4!x8lJ*XW&a|%*Xk!n7pdhX7-Sij{!%w)?rL$H5M zg#3=+b`aX95JWQn-FE>u1D|`Dn^lD-4c{<=Q=N314r}Wy9xz{@OE{f>7!sbg%WZY@ zXUzR4uuDzWRP&_cOdk9CS`m+>fLwZCac-*CoUdLg=s~`VfOlmIcD~<;j}N9SqpH|C zx$du-m-UfFk50!d$H%mHpeE-1sDAa`px(u#t9;pf^4d!GnfF?onVo{0 z(@(bBy|EcgjTNdo!1dIFD)usc<kVYyE~$y_Cod2#vxtX3 z$w0$3!V6_s_rsr%DoGqJ&xD({n933?W*#L)vQ|qlo2fnQZ8woQeaKJcerEkqV|vuB zr~JT)94k`&BvPM9%yy@wI}*-?*=fw&pg3co0UuC~uhW-UZ_boECc1XG+JALXv=B={ zvm`p!pR)a^xV;=RJe3fAg)ndbbuIc>ef$t5M~h-bwOiN%U&#b~#9H<(f+MY)s1uSj zxuJC6jxc}w!D)vi^t}&i(y?_V&`&Y0KpaHQthw$z`A0H?!$25)#-OIa1FR}3xz9!n zV@C^I$iso6TUq#+D50kh({F8xfmJ|&(J^)?r%APrNpJ$ZC8qHq5&Bb!?t!H}GR12_ zrw&-OzCGE2MdviwX1*6=C~_ll0r2Qjv#V`Kq6~)B5~n!%_-m&M-kb=olo5(J;48mB z9xoQQudg1cKXb0m>m}G(CTN79%XYoX5vu$=h2U|N2fE5!5aNSP`P<9aHR(z1P-{gc zCZmA!XvfX@*>w5G&I!kBJURZ7^IK$)DNt3QhitNS*S{i1Gsdm(6!Vu@auc?8B_$FpW zCQ}>^^lBpjmv6jM-ENYWCthj?-~u<57}B`8pbr%1wcKfu)E%Pd{hYd&gf*M5mjSn? zL50HjK82tVy>ca(4iPnp{pYhy*RHLX9#lkCnccab#?5Fy(FQ%^D%dyC2Ymmzyxn0M z3~lH#kGd%-+%FrI3U1aS?A~jomvh zO?Kk?$$-f9??-ed~`j3eo%dUU$|V*cpKBUYClJf(vVS70S#yQlHe; zMT0w>!M88rf{yMV;lNF@o~bn|U}0F12wAud%=PF@X%?-s0Dm(iSi8pEPc~q;A!mR4 zshu%VqyKC*8;>m8c~G-)9dH6<`yXSG&%foAgnL9Bjj$rUcr^Zi|DZ<;fSWJYd4zl1 zcBdLPA=^$tops&y_?W(81AM*$RPRRlRNHyDr$-iK6*n(Q-=x?$qsA??u$(TtBKOmOCP4)LO4$wB9vQ0{cE7h;qIvr?2o&gvG9LABkS`f20ClzPO?=Gb9!gP(reHwDX}nr)E$lY_ zyNM)A4lane4EB|agL}1g)TF`(tl1J`;8(}u^;Q^DjBKj#xPf^qa zi$#Q_;Ia(BwnTs$IyRcdP$z8It1QQMmJKC>v~F#ODEh5hMeyWOma4#4lzsr49XFmqW(1puIh03U=pLWTQpfnl5OPO|s0TkI8^v>C=n3FL z*RNL;ZvqLBq9-drPT@36bV4JIpODBeL)!QR!*1&rhRlZKsE2Y3g?Bp3ruZ*#bgpq< zDI8>O5>0d$Xufu`_lY{1-`m-F2`)(NufMJ`=}}mafp!Q82k1iEn`yFj!5=&Of^sPQ znnrx9N=bFh12|+HRQT=ToZ1rpvy0mOL`xE+FcDD+V0}+VfrKm|s@9f5!-t^PCtXUe z9McUPf{K&;`beP)H~7(hOpiQC3Se?9r=dBYk!*k(oToIKN4FiGqrqZzrIEL5K12xv zk86}u4_N@ay=iegR+ud;Mm*o}u`KjR2L$fa({-@Y*#9D-0!cMY+H2FfB=hrLa(EYw z!g=+|8d+^Y??uF!)+Oc~qNV?Qb17>>vKNRy+A|PF=EIpu;cY;&vbe;H&3A1Zs*BYK-*~RpYRPom zl09v@Fpmw}r4@OmpzkNx?P#+_&x^u&Tx&Rn5GG7e%h*YWAh}smCAg2%|G`jTvNF&t zKip}DnB`?9g+CI6>06CXo|))IB6;7s4A{ij;Cy4t5-_SUFl_{8DuwiE^Kf*_OLm0D zp@0T-dR)HUrxL90eFx|)GMiog=%_aat!YTrqf57~?BUX?1gw7a0I66bl)Lqr?X`&d z`#Yi+Ro|VEK#*)S?#=R%{0~OB$}}rzr@-+q*|!bNy5V6UMSn9`DkQ%@Wq!==oy~hhwDKx@k9{%kX;q#^*tKTiCcGC@v*(!a^t*AN* zKR>uEq2NX*V)SgzY3Omf#I(HJH{FGU1$_(Pf=n?#{Gk*sl3MPdipSfqE(mf*`M_p! ze3UGt*t!FoU27=lkM{U}(xm$a_56@na;<~Fak)9)eqwPRuX>a}@aPMaV5;G7?8=QcKZ+yU z{0Zqp-WFdcpEuXU#KO0i&y`%(vncA_m(6nE*I{X;YhsM7gCMkYgKB{~@c4bh3JyEU z7>Lbw>Pp1gtIF(YWZ4x1j+d9rX+;7IHYs@MUT5pBq&z_E3ha61Kze=oOx6yJ5dJaH zg`d;t_VB)oYO9HYgxwxJx~w3|lpnl(jvo~N%0z`ew-q&PM~AsWSDA7g7qVqZBj$8z z%)hJHZ%aLx{LJ+pA#XD)&4nZnGvs#C#63BhKC)0MXBN7NOM^>H>$%b(u6WYiTXDv~ z3FqV`TB!1~byqZhY4%~j@c1Y_dUNs~h?l*gwikfV(u7kJWl7?KK{Yu|;|E7bLMiF4 z`bJ0giO@Qm=W(mi!Ya;q&#r!(pkgDT%(YFBEyp6!-6;1F-qlyKjnH2&8TM`FV_n;& z#-H4@954c-ck}P^`-))Wxq3hdh-`}8^x^0Wgthd=!(b;7nFH+N=mUcEYt+QUP@{XU z1A+O{pmk^GV|3A|L<*raa+rM^_q-`3ey)LbU|Ow&Qglfg;CX+Sqkon4e;ks?*(h8u zXZvFy5B6@K5dFhJx2;T3QQ|67H)ZLdOvO*I3~KmDJGzp2Pg9T$JF$tG?6jw=7!DkP zOEKL34rvjtE7}Bzz3HJ<`%}EhpRQWrR@AdXV@xV?>JF0(!1B~vX(nJlWlT?k`nnu7 zjN{AgFwhr=U|0|K1RYl9GK>emY>TR$hZ>R8A|IhM;Qqg9+8%$f?m)Fqa33Lt2#zCg&c9k(e;sWkbDA1Z9D zVO=OOkj0zWSO25bD?Lw$n@GJjYOj9YA-lF0KJg*lqZd^FU5yl!sT47qj6fvc)2vBz!)X)(O;N7$HcT?@Q z0Y(Wk2f-Vl?078Dn_TuVuO3}%#wBhztDw$=0KGGIxb{Zi3RuA3hB2}DEg1+T! zf+XH%nL!p2AP;|kJaHGp76oCI&m|#C4+@a~a_&1l!Mim#m&=oix$v({_-eRP4i>~q zFny&ch(Uzly~G2jwi~P^oB^AIDRXZFXRrgZ&sRU-_#Ji})UfUW|30`q?EiO<{`2gh znwv8|VgeoW9Jng*vtQgz443|aykjgDBpWfN%~`}m5j(;u!EY5PmK_x3Eom9`l zh)n`Od&s{i>JM(#GaaaeiB!PYAf2IeyWJ!m;gJqEd`r1%B1oRzD%i^}vlcW~($8%C zw$!d}&eh1~I6WMr620EhN8-OQ0c00s4>$r~|NL>Fftn3vW`+w~GLKnJKvQywWOf~< zr}bS?0Wx%Q%01W#ke|TARwxr%zTvX%Y9F()YKsmm?S&n6o}6-(GBesOFG1??iJV2c zp8#b#vI76DvOW5ab8%hw-_=(Rzh4qSpu1;0_*Z!G;!?*4hY z#P6qn#ykNXW0Aw7xO5H#N;0hunHsACM!(f)dAT1RpSXjYVw{kIQ$M~c0F#Rz0eX(Z zAAbNq`b-lo=}#i0f5pIaNGD3?2>XnS)XJV=eORPXQZn(3jElM~3ue(pX8?0C9NCk% z;1e_K72C>rzjW}fMitpnX->&#qjjbh|plcRdk1eMnQfWMz5x1-8L7%G7h390tc&8&<6uh=#3bt0Ao9HW`2pne#94v z8As++{pNtb(d2(}!j1Y&kU)OFfYDS^QcQ zXFj%vJKhUoPj9?7k>|c{^!hq5AUZ9Sa4d;J$U+;fpfWJy75_(!G~=@Op)62g>6P9w zSah7eg>_b{`ifey`#`;l6>%63HDLKV=@I85&UAqdq``93L5wNi;@K95##;6j+$Ko< ziuyy~u!R{y**>8Y z=PqHdQ=9`j#my53;DY|pKaD-vNa+}TTnZk+d&377%c3XYk85I$^K%|hXp|O&vDS`3 z1LP42fa@HOfe7hn{YxaBEV8wVKTwagWtF}+YZIUxb|Y(to9FRlr(R?d@fdv4_-$J8kISayS5!aDQ0apOX7GpdqPg zH)iCDkWGBh`95uX;TT$;!bLu_xFMhyDgSDu)Oq=e~a0OOCW!BaO z5ccfIn^AWNoPeHgX(9n&IbMJPs9b&j@X-GR2(=}!WNKXXbp#Jt`i0s_J zQ;*%){f=SqsG)MqZ@5kq2aM0zvX2Y=YpL5v*5<$GZ1J ze3{e6!QIeoss9Vu!c3^h11OGIwEm==IK5`5e6F&)vd13C;{8Kkm*Ozrq8FJFCs-bS z8{>KKnD;$N$NGvM=x{sPh!g!Y#EHK^gq6*jA0#FmTEFW0@vg1YNOmlWtC#QLx1Wcg z*>SEN*rLBs*k9D=9~7n$n#x%(B~Rt3NVRdESh}Z=?cYp>KoYuM^}OB7XdG^ENL8EZ zek-c<2IeQO+N6m72s0M1p3r#BByO=1}K%D)4F?UqoL>9~!Bm{rpxL+|LZIj4fXIjC|abFsA z>}4~32!7cz)T0gE6AZ7H+Ly>e5BYy5r`4vN_2nUE%}C$P*nY+o?mD2gILL%7DBYF( z#1^aO8XKul(MlhA+d7!wT;Y^Br#!=AxL*QV`n>6Js?CsxvuJ3 zZ929n?3u&a@p{+di2ND5sh-Fr@GT#}ojbE3q`1MxN5|(f(90!e}7$ldLemYHozoQ*92*D}cfkyH2DHmAYX_w)k;)>R}R)^{AI<*JAgvnxC4R6+c zul9PJWjK}i4I~a1Qsp|TO+PwAEanA={@emZ0chWrbV~HhJ9FHT$YKg1g>fOI4SqGc z9rAJgpXtzlDI0&vtJU)Lw)PRmuiA5)xdoSc*eaXB_F{0Qi<|qi zC?kbIh!L}$NU&yQwg$V+b#VF0Hp z7@F>fO9-v9IDK(wh|uSZQgYhwI5p6Ebf*=W8}mQN@NW>XP>y?y)|3vY!9rEXZo{X= zCBGR{t=W4g5bVF44x+|8!_n_0+9j|KT2yb6jTDpo*Pn9zHt|c~t{XlH0hG#45U~~k zF|S}J0y>*XlTL)}jlfMid)37n!!0Dk+F-KcOa@x(5A^=HS2h3i0RS9Z&6EQ$A!unm zO7OfsY-uWC{%y;2mDZR^_^+Yh0EcMm@zL!CepF)V+{__EBncwTl!on1=Jv016NlUN z+>cV!Zmf922BPZjTtMgm@p!U<_8K1X1?f!fKQ-|ad35JCfD2XjKxxI_gNgruQa1qU zaMlaeFgF>FtFnjmU^%A_BWeV`AqOj3ySyMUG4FW-okqv|wRo}V`Uqb9F>qKLe2Ape z%d}t#&R+mGRp{;7Gem=n6{yx%K0dg-nF!HjO%CpR(^^5OPy*1k9MFUU)m}7>yW>|` z)*|8KU0}iU%CJr7UHnsyD#<0QW=&pfXutv7H)sQ!oyeA4>zXWmE;xeVnPeR!`JLJ7 zrmsk0HUSlO#271#1ArG*eQIb$o7z0MP1!U$L3#b^&3LO5*-v7UvLp-V|C=!XQK@EJ zEP%YjIJ5dPc7F}W%00jI{jN*Qe3kzqRG3fVD$-fjHB~qw<>1@fL}A85aFZkxQPDL6 zfDJcoe}1hcd6MS)z#!b7Pwn{l}<$4t4L=`uZ;r=z|}o^;<`5h`!Bkd zB^at;HEJ&`;ku^(y#&id*;S~xc5N6fM15BKBa^!2|BA-S4l-bFI^`_Nat~B_pbIaaKPkk52TI&-%a7xXyQFZqHW} z#x+5v9TmypTeHSqV*;KaibwWXNOP#+-7Zm(zZyt>St*B->tBhQ3m9gh4LgO@-|lR-v9G(4y`P~i1;_qx^j3ahQJYIg%=dERqfS?3)oDFSv7~to0>AJret!!w>{J zzvjOPZ={tnjx3Q)eoXi(`VNu!&;22M|K-u&1i0OTI>`qr3fO^6UrwxUb?6*v-KNkI z-SBtnc{BIg@~=yn@@Q>--lw$%9n%*OQEr)BhM-#ek*7(DLhv~EP=hV>ow}{((Ep;U zz$E3r6qfW&N>OfhDU{t!iyd*P4U9vf-6fl}aHoy`O4itsb<#ahASJPv3CA4!bc|BR z)R?KhdXDx6q!0%3=WLZXhf@~NuLlE$88gT0?C{us1q#JbFy~(~U!YpcqD9|i0m%s#eacZG3D6Z>o}p?82s20vq$VaJW?mvN^AyZw;4b!UmDc*l5 zIgw-zE8UU0J-o^?8npg&z%wc~1S1L}{$O4ok-ZHA&|7daUJ4|)s5F3_Q&3(0=*(|> zqJlf6n80Rof!b3A3SIDtSpf!vk4S849-SD7`zUEIQk4w0Q2%djNRR&NH9#=u5_BwV zuTv2D{k1%ZUdc@Kfo~nFP!{{1+*`}n<(5ka*b$hQh$un&Mf?R&)VUiVV>8$h8BBdK zAokf_@{@uaY$3yG-OWHbX1Ys_75uBq{2o940s4O{UDJ|qtpHzkDp?JgRnXNq6v@eV zeft_@7@)x!F4wG0`-43-KV;S?YpW}+yz49X+Fl6%Lrau17{Q~ z4)|O%si_S=Ly+zYP~d%lfxnL)y%CTt5rEKtU{ALEpYfz39g%oXC>b!rORp$oiApoZ2@%#{?Omt(W3 zm4AQU-k{;XRM~&Rs1^yg57LjIcBo~RbX^L)!MF^9ak{N_F3sG|I&L-mGcC1y2PFlr#CKx)<;^lzmWNj%{${T7 zwbsvhAMiUoZF9Wv2<<3Bj8PLYtwGu#WwmTZMlA!w(LAw~x%B4oA z@-iQwmrW6nQ=eb(-!O{Gk9(*oUd#~44^C3{Wu<~AxN4*9jxG3VxI1J8UU4Kl)3LN!FNcYp{`}0bB^&W zJ{>jDf3dMEh>E zfk8UVPe&&n3kKT*UHkyS`t+2s?MI4sa**p!fUb02rgZr206Un}GUtz)0V{i93AkUQKQxI^ zmmOl#ZS$+ePtPTe?)9zdfq6O(f(8|TbB!(=iAC0rjPMe;n+uuQGre5&_`_Xw71$m^ z%=nwr!b6Ph?VkN3yTnf()Cg^5WI07Aqji=yh4ua4U48P0lP`Nh&4T(>`i(e>E3#5uaz28q_?e&-=^@$1jHnu%{}Y?z9GHz-y> zPAS!!Sg%Qs!(I#Bgl?@isCQE2k2XUrW26A6%*a_N#z2rq=V*7;3?|6OHdmm$yRHWO z6%x(8kBW9>Tr2YHnDo=#3&=n1h_+-)BE)rq>-v_4{N}U&)CvJ7YL6xezJ}*%TFglO zf#q13;0>5FpwT3+U_< zJ2sNrMPtYH3wg-93e9}?f%PM+P2Sp1otxnyEs#2-$*zmjJFX8bo8~A7X*=()Tfe?>3^Wx6!}86S zBdh^*dUje6BorcSwQ!=9Ou_oD?$fovLn98j`6_TSk~#`+?u;681MBg2c|HAbPxgx{ z()&j!pC|+=un?&l3T%X2-dh)AO*bmdZxD<6w9SDD$=}aSX}_?!;!^v{ePO$*@AHz} z(VaGz+UqV7`+3#G)Ba=IlVoUM7015FD#kH`P(A%#<|ZEm8TFZs`|8gT_rsMO{+4H# znK{te6mFy#m_OB?5lEHlWr{E|xx*(%c1r`wx|0jHh-5~YwL9@|K>hPO8Tz83IgI}_PU+(NtL8V{X#(NRh7X3Pw+pr3lQTf48Bm9~9XLz9s;*+|L}_ z_8=b?jo5xV`rIKS#5P|Ck4)twamKCB*K9OatVR#mYKhT6Y#{kf$ubJ^8S8>PNoV-z znG@WZ;*9AkkY|tzLK>9W6UnG81-7f>dZlR+rY0+02Niw34fO;29&nA4ym9$Ub6)0bG_-m$fYm7cxquuaph1u~-DJRd@FV%qU565x*h4&K=I6X4ee% z&c6VLADY~tCjfgp>DP9I4!{Sk-73&~t$^RJ@5yI9p6UFCMn zw4L46$ z6VN72<5tkXHL&1Cdv3f)TX`7LAZU0?hDd!P(MQ7{r%XO@z>PDn9-zMTo`8X;sw0&5 zPghv-eU<=-S#2`ZV}uEJ+T;vH(R~~sCuTQgxkg8&L5t-micTP47}j8ipWX@Zr5e~w72dYmRk$QF7gwYX?&`|$h??(|Cswo+^}57k zm+P3Y3w3Ym2T_lDsf&k8@+bKkGw4sgTn&(b+g&EiW$80r!29L1mU#a>7vXdR)YNOK zcfP3|*zAbwzm7)|8|fczGdhXDc3|2cU*0TNZ~0sx9&BO%3B}t-Ybn(d=ZGXh7T&U~UOb zlcfb;Rc)r~((buv0a%^<1`8&n%ih@oJ~QR8bZCpF4gM%%KV0Z7t75+NVG_K1o}q+$ z%KJ$;-uo*b=#Y%4i#+{hP<4`Qgetw{Mq37AZMOzk*n;{k*7H%QHK9$A&l$;)+gr+^ zu9TaE3ZqS)h*dayTkeu$8nk6_u;%DeY(huxgQmI9HZ-c@#pC#o@IAota^(Q~^YE&J>95wG1W?G~ zd`Yt2C*FVJBC9t&Vwh2GX955ux&Dz19%<5{&qOpa38Y#d2Xa!E&}*52eho`Akh_`2 z2f746S6krfisZDP7Xj%%f?oeLY4xQ6*sJrzFKbg~M%dd<8_iD*)ojfYmbSPZrpw@C z{3v=Dl-Cfb^yTSV#E?A!pn2XZXPAp|UGjW)VUL-nPCb~h(^FjVhEInMh-YztAq99f zQAlxpC4e5ZZvB*bsPi!k(4%(~LW+oKJpf{*A0*lEfQ07AEdYA9ptSWfc4Ux1B2L2Q z2UKrv|8yZ)g*W*4MWKn+%>WvXRf`DPch*!pn+e#s8na;b1FYc{4^yTD+l#d>i$pQF zIDJ){tM)_c*7iLd@p}$jNIErjwqQ>Kro$Rs0S|<^qe!1f9Rpz8S~~zGDuD$9XU3SI zIU{`qpVbKHBS^Z#S{!f->B-(=a78JGGRk;g&A*D2Oz_;vr^noz-bWt$q}=Df#+PHD zuX^qWn+Rh6`{RqZW%Esd;j1{MTvXV{^2pVsV&jt_f)Nlvz(EJ?%*{CLy!42KBw z0ND5$YtAJAp><4v5a*}y$gV4&&1Pnax&E%82?&C1l2;0DKilp)g^YL&!PlK@8D5HS z@Pke@BSt#aTt2Bvcc(Jyy{YgCpNc-$CHU@sYWJclAxZh3HUenF6G-T)J~Ab(m-hW| zgMSCa^)Oi4T9jeKSQLFYY<3e^^#L|XD=GXa)+Cc2e3al`YfBA#0Ey)T`F(02q6Bs4 z*g&5tY65`x@IyP`sVg6}SDAT!WPPP2?pe!huxuU=8})NQe5iT06nq)5B$ zWD&qvyj;VWL!`o_LL?0=??NNF@cK3_p3G{ku3@e*ys;gHKIAhbV%|z`-kIG>7?L(6 z;*vP;62+X6_nD&@Tg#OFcIwNLrL3V1nvJpj$VgE$ls z>wM-Y>c|*9LD{TuU5~1R0CVvt8PFE50~f!p%1!G```c>q?ztJaX2ek3FHE_PsMG_MkBRcN>jWP=?*JSzSIs(Y0F@svtFYmv15HztZbo}!q)m|{wTbyq zZX~~CqMzZ8q!#0*P6TDuC}(tti;$-C=Tt|BNhLPPY~JwmB&c&3eM^UnZ|&0YOa#wvzR6LHzlM%Mw#E=f5Sq z`eK$t&mJWDVI$jAG}W50!!AGKhazVpqAS5V zIT$Rr`Rq){LV85wUgU_#IzVwT?c4G;8vtLt@gn5J=)=B{~ZWMTiOAvwzv%-y5Fo7j4gPbVOAG zHIj_kqXxo<-jt30hMWM$1P$BW67iX*)vejqvQFMBO)Cy>x8# z9I*5*B+!*EyL9=qQ+U1+t3tYod^XvxiN@sX^W%;t%YGNCxxqncnazHP5&s}P@Crr` zxC%r$$`tWJP1PWR;Xpq5)^K1%Ai3_rsV|l{PGMpZ0E{jb*-AgKXKrL87cAkNnpqpc)b<$iFr0>o5L82Y0+v!j!vtRDW4Goq% zFQRJzN$K>lIp3^zWw1lM`7Kf7T~WX;fI`954wM7*F%5CvW!4Ym4 z@wWFiOVNzNum?+Wgl#zCh3%+zNiu6Dpk(^Ql1Ahhl9HgQ^-t&n%hwSanxOrc0Yz#x zDv)9=l+BYe37$oH+5op}$^{s)9oT)!b3xPbu51bW9KOTJq*&swwmd7~y4CLu_5{>M z^do2dDzm|0^ljEaf{iR`Ctzk@{q6JNT~84$M(d$5{K8=!izdM0P=5S)R1njmbfohs zX-_2aPV)ySDgkKhz%}v4MiHRqFkcUbLE+w;9hayAQyb7uZw=hKk9y%JL)yF>^#L*5 z#`o+&Q6Xky0s7z}x-fT`d)L^c995oN%m}91+iTY}TNbO$Uc7Ve*(aW0@@iaH`z6u& zT`ly{y|r0o@vuu>gWJS2-uxdR(VFd`hq9VaV1|9an5eDyGpI?>aGPgdVGujKG}u6leGY} zGC@@!zNRs~EE%-Ik=cncH;OALh_a0{DOVUv_#Mwn5vCh=%4gPoe~PkQvJ z{Sr_zpl$`>IW~yOA~-v&=sxnih(v$4)nDtO9w&RNU%5~Ptwy@6QG zCe6%jyxs{0u&o6)y^mpc+lTChvcU2sVgOUgO432yb|DAd-DZ$ z;NFi=gt9KnMVAwPY;l%auInC9rCud-hd+Qm76ZK!{`Sh472qd5aEp4O z(gXaCD7tG6d)L)B=NLWq@s8z>?VBX5P4| zPw%7}Hx{DbKwUv1tn^njj(We#3czlh#00RB`3N8{7NhonwB8(-|Dc9sUi%zNfxQg= zo(=Zbz**w~Tn>W6xo3|WH}iqog3GO%gyes`q1PDEDhO-sb&o?#u5~28nOaRWN5%H$ zM>FW{G8d13yrJ=LhnV`YBh!e}hGkI={P{*<=jepag{6-{*=?<{{?Q`5h6-YU4MX;a zfr|xuc?|HjzMyqOx;)k8;Is&Fph=s6_LBo773*j&Pa8yx6zHtD`amFN9Mct5Hpoaq zld*chEt&mB6J9-Qzgk}^|G2uDSo6|n5-x7EGaIG&+7dboUEI5tB>Ox8Soac#T|L78 z^R-V(>znXIx9&!VS?H^@M!vjSkR`m*fve$8Y&fvTEa$n(#tB&STOnK5reCv13j`2) zt8Zjc2^H?OPd#o&Di6{@*XfpaXv$qZ-heBHV)cIrlPnPkigo zPDcqulU0}EP(FG`8KmpW!OI_0i7&Cx!x;m2sX%L=pYfpz2+=MQ(x4TXSH@a&VBb)6 zrW?en3lcSd&Z|W&xf_x_y9n0`+<{*GbJ;tmpf1{mT*hctCBd+F>N6U{&figeNc*4e zPi_#dH^oh+>fwsp_hqK5#E~?YjqV;;rG76UQ^KV||E?V6`@N|GbQi0fNs|`8(#!S2 zZ@w|%JYR3nju}t$f`Y#nGZcV%Z>|a(s9q~mcP~rY(31_qW52G=4>2r@Rht_m_?w}s zYx2{*cm7<;_ z1`V{`d&>93;PRXG=50u|{OC~TK1y!882oe~we32HfSuoci}3UY<-GqMw#Mj+zgqZ0 zz-F&#Y<+v_Ol&=xw*v?G2XSzen@G3+VYL3wP)_^_@{oZC%$pgx-6HASkGapol0fAoc<_z(N(VOK;K=K)Q+@6=`}E6$NS1 zA=IFtpddwB0#c+Up(Q{_zMX(q@AG~?9fRRHS$pld=9;UVR;w2={4yh{7Gg5`Ohj*b-96HC7^>Uv1u_{RvYVT0uTo{bjfbhcE9i zH+PG;ZntZHbB~G>ybN}%1}ta`xEyEA;9kZYJ~ih>-1WZWn+hb}PIA{%eL#dBXg!Hq z8kh{x&pO|a(eGsxD0~{)o6dwi4OT&phqR4ar|;5x6=(uY8wo9(=)z1m0-5{26C?WK z6n)f>@betKxrN4>i=2ea>xBmhG`T{v!}~|J!|f4&dCAXrXVHvk*q^(4N>Sc}UgUpY zI|}Aq7b~_MFb(M)zH7;I-|+sPx<+_)&+zbJs_b9cmkZVD``v~m#IB4>uHg?vOoZHQ zOVuk#+zVASw`)^++0`kEa6BZ7-RJ>3Hu#!2>BBY)j(q}I4VdoGisZm~p~C5|LKU4g zbLG|X%P+$v!B*gYy3qIioX~;g2!98r#A?{_R*@drcOA2JKFH89R0y=e4HwExTl&}Q z*NhKu7Qj5cRiVJ742E>%P5(m=QJ`HO(@iI~Fbyxz<<9Fe){fp-9xhwyIw1_8gVb@d z9OQi==}it|npEA{V$TWgJkoYPy_<;_=*A*oota-8Y@k}ZlJbbx}8bsWxSTA?5SQpr$bL#gdG;A5rsi|xlLhxm~o?n ziwx0g&m7MEJK*)ZmEh}$*W@+&cFM@m!E$#u>@{@nivhP)+5?slX?LTg><6-*oG%kj z^_-O6w7QOIk%rfoQ!g3*;rqE<{^c5Pb6MAc}H(>$|1&soC zhhT(e@~fjO@#WuAYL};E{~BxQ?RP6)N(?9Gi2XWvRq{HD`q+6mEnrBU@^ZprKZGYI zzp8)XN&K4OmMLF%fRkcgq~M1+R}-tOC?11wJjiEoYyumh3tFcIz=0dj12f>_fEo1f z?O4lGc4jv{X5vf8E~AI!9SZSGnH#Ij%O_Kc{($%I#tjGhp^9jwNP&dSel~ortMyRr z9Jg^@cfuyQV<48WW#EquG&S*Snp?;g?sptq8l)Q#sn3d#bwtwREr70M&t0gAZbwMg z0j$R*LKbs?8x4Ec;EX}&w;>C4LP*}9Hdv1t^wOgF`|0`Isl`i3C+UXe$Ca#)H{Aa0KKZ=r=43Wv2-cL(`pX&IR2%I*=M3 zhZavjOy1W<8mUUcxns%i6cJF>0;e|w??O4!4H%i5s!dw0oSV2CTAaAYMR%b82Syz= zGS&Lki%cwO(O;DNzA~@+dm5>-wr}QR)=bRRAl+Fz-_dTVS4_s-S;7Q-5tv4;fcf17 ziU!o5cJ{2v7B=O_{D6^U@z^c2xBy~s<6vl*9MHjegA3t5tjr-zg>$Hfw;a1wX!Coq z3T{bW4ww{{izIjW?g&8(jr$O%d}yuhJl`yq&Tsrbu)%A>cuD>+;7hVHc)X5yFUqk`>gXadiwo%lzHG z%buKLb$9RV{n(EBp)Eb((jO5%K52g531YFlxS!#{#xj+(f*t0Q`=(k=>__icyS;hT zf*5ec+z^B!@q`$~FD!2zevkwbVt$+9bx*#CrX&vavLsbjA;vI(Gn zebQ$lgtu@Rioy8bC>W6mOe-$3!uRE}XAL(8{!Dpu;m2;-pgHfl$!(Q9Tvji%xDT@P zm6f~}I_!Bk^!KT%Ty>!7xG<(lrFFw-xN6WwtPu!;v(L|;Z=4;$tY-KxRb28wD`1YZ zQtmAubdT74|HK+BVf7J<$cMBv_3!yfZNk}~?=9pY*?oOL{6A>Z8HcIjE?i1Px)TQV zf4V(3wNJ>jjruM!t`I?k|6MJV2<_`qcJ}g1cxeA~dO@^8*wOt2#m-*?=z{LoJlOFJ zT^{TmSj5JtO%{IEmceXs3Q3_|+X8nzU1KdmVD;PWs*Z;OgxN^I=zTgvuH$mAB^9=s zT;~2Cq=!QOI36V>=k`G<(DK~b3BHh>L84+XVfmBpCs6jRp0R%PC=h0~uYA|lCD--& zfI9}IF8lcWuos@a$;kV;iW-K2>xhZRYL&ib4g^xu_&u-*A7>|~Z zx8#;Yqk{nso&N0Ce7>3^B&b4s+rWw1zD3ad*GbTi=W9)n6Uq|?sh@H7ULmCl>*bH# zVzA~U4b)cBrg!fRVODfjm+_0J56QZ8{PgFVQy^&X;j@b#^8T8uN8YT+VKC0ZhVYm| znS*2(DX)UtM9z2I|`~xG82nQ&8pdk3U;}Wd8nAX=P(bT$& z3w+u&rwR_MXdC5{=dRUJiAf*pPp@KSZokQ@xW6Xru+CVnxixed<_bZMhbddS#SX)} zlOgPeI4BH0(gb#QXFL>y_ET>pS=oY)KTTkdM&MEox1e4$_1t7H({ID3Ta2-v{yeLG z6SI|0i~Kv>y{yix?muh6zka>8@B{To1D3FEJByhkIa;anRN z-A(m8H(9~x>Ps!YrYqrr{@>olA|*J3Q+%liqhS;{UP{-Js=qv&Mcwgh=BCL2$r(8A zX!_W-d=e~}A8w{S=R0)uVFKdQ`TVLvZTbWH)5IHn8P6`xducktK;v0cCIWtM9ihy{ z#gy-&e|;xlkm}REZ{B$G?e_R*Q8g0G3pHiYD^u?^-OKm)=N|gk)*;y|vW<;bUn85I zipL50&|O&Pe`gpPAohB)ISg*^y3TF~$MXsAu-_iyQuMg7O-oX-lZ`1+9D_^1RMo^w z_x_J=j&0X^T-Q30z=gk0M5#aC+K4R4YBHQR{zesuXD~l@&n3X;!$QW&5GcF#bvJ8K zQV-v?6HVNOZq;VnFq9|scY}*Q#BX}9T%%t?TJo>-0;i`QMF*NeRDtZhchsijJ_@L7 z{jzl6rFDwU=ZWfIc)$&ry5s!YGbgi7H1A6u0W3+DwjW@j{dl%} zhPQx9h@il7%<*5WBwJt4@LL1${vE;BvUf4c5st)yX3S1n`ylrCe)1-mC8 z{$rngXsI>b6Rttyg)NP2$Y;L|t8MV7{heknxX)mlFgQwwh^8gGeH|kPk&1*3$f^*n z-7LzGsek53H+{8l`7D*mX1&Ouo-qK{@EMC?$!E@AO|4{f@NIa zjEY#)mwJxx!P=$5_Y``bayeGP_DW+7H#SLQ-D&7RYHoN}AnQgiOBl%F!CtAX_duE+ z<7v(8+*ReaKKX?^8zQ!VF$l(MR-55#teC&B7G5)w`o!u^}NiIhZ4baOUU9j{K2}0r}o9g2~W2XXuEM6ES ztzLixdWDLySNFnKAWmfA^2aKZ?Q8LwAxlIgObT}X>j%rb1R^9bEtb!te!AtF+NUrs zp>CvnI8u7&*dGbzAk4h(6zr(Zd{gR?JNOPO@uaIZ#R}5S_Y{(HLn8YHZV$kXkpyK> zo4WzV_LZ%V5Idr1&u^7weI&({JGj{vb2C4b$H$b!vg?klPW9zQ9BLx{Bqu=o@|=h8 zxuLR8nD(O2n9s`R&RMd{O09!Me&9uY6lk`iDeZ`#GyO*NpaJ&N_9UIjTN>YB3sQSD zhV=8?;ImRC@U{&QRMFe%FMs5h(BOI*_UyY`#iNlxMey=No;is@kO9eo)AINAY91GM z#r$`7hd#e9;{wsruW}k6?vU{Ud3In|i-)Ie*tlO`LQw*_Qrm2 zvMuS)s2h7H2{c91b-T|JZb8Kz^^DT_2DdaGFcRA>lGIkb0D%uc5^GgiYf>)R~v zxPzRmJ}&{s4Q&;$iHJK0+->aw4(V2aEdgg(O*iY|o+fUvycD%`Y5(qCeg?x|vXio( za2ixBEV#gqk54tp68~8|GUR%7rT)FF3*J%2Yyw7%r-e0=Gh^l%A51ry$e$2q6J_`+ z(X5QYQ+qEg>(!L)uj_LKrq=MXR($&WX%|!rxA;VtG2n}QI$f;mK7(4`JE6?z^}pU^ zGZHYRR~V{q&ObSqtRa}hP>dvk6OdrJDSu@|3gRWz2sDqRFA&~X zbm+*^Z(;9D;E8S9;g(cZQTMl28xd0^vuuS;aB6M3SW6$7qX1&h{baaeot?pn6h%PB z-?<$an$ib&*_5Cg)r7VVv%WyvxGYbq{8BI%pTBfcLxuy$)? zE0^GSEx^GzE$wyN+fl|#C4IkqhTVM6CXaPH&|-~)su<&e5n2N)Gx)6OBu0N zy-U-dw8)kR3<(p{`sTB55A{p06%UYu6hl7HVzzNDef3l+{p#@IY-9E`Ig_hU21wAe zB{7h4KzCJP9bva-BJKI7qSLVYbWG>gMWm@F8sZE35gatl5@KyygFDN9aH7gfWagB% zYp@JvSLm%2@^xWH8xK}>VA$qMES$~pu1YU&6Tx(NO2X=wD2)T3J!i03XC)gnw1wV; zN{Pfcv~wLhk56m$msm}t>Vf9w(~m{@t3|eQVl)Yq78xQ+y8j*a;0%60U5u|xN`1&4 zE_Q-cZBP_*+ul59cjl}(b;ztoG z3OaX>(p%skGZ@_1f7h=Zs6l-$#>glJ42IF|N5*^>=u#KTF$EwXMHu=Y)^V;KZ946$2%qPk!gOjlpzfOyw)iC?Y9sGwzQ=|*Nl81xnk6AGh&Pe}u z_;qzCt47xXWgvg1e=Hq|8#uhhP6Rv-y>lO~et>OpRDHnSU&a~){IQq*^_#;)xQs)| zTGla^!J_FKR#Vx(HK?yH{P1^C zDZ{j{xUMuOn=^_Rm-ev=*+Ic!5U+&s#R(D7pzhsXH99?w!}J#+R2q zh)iaYGv)avXf^*K+=WuI*`5i@jD1nl!v{+P zAIlahD9s^-0md}+B30`u>h!W2*)6c__?~i@<6CpT2Y?HkBXB zsLED(U?^i@Mii6|KfCDxIHrU3@H4Uqxn+X9y-)VwItDD6|GVI>4%*5u4_bV5z55Gh zSjt4iw9FpAv=n79BA^{J?msC=$1fz`hu?*OEj}?A>;HQ;&h#Vu>?GAs3c^;S(>D-= zn3-oA`bRo+KthG^asR~>_&Y<2wp6O$#IB38>c4(Vx9$DnAxcIdR zE{ch)v|sXJenSFgl^$%zjH9$D9xU2eiH3Yjh7ow>3jLdXL7X>%y(H#h zkMgdgz?&f-v#&|(kht@3?@%zGin&hmQF^!>SQhW$ioDMzjKaOz5|@EJ97oewNh@>EW=o|YDaF_uq&j@s}s5Hy|a<$v;4~DPIu)<)eCMP zUd^}9;_izF?;Q7iX#eo@ilzW(qqn6pH+SSyuDvPGpx6L(r9MdP_kDBsm!jY z<-6C|^n9?d&^@_X>hWSJhLgj+&%&UxD^w!E@rSnlc}|R=Hb+gyTy?jJr+NdXrUb~2 z*Q&;#5%$vIg%>#kHgbEk?7*Qk<&H@B^W&625Uo!UjEi9#uSbjHTI2wEfNLkPEI4&d z$_e&*Y+Wqqs;&?sSMli3UkjxX<8LxL)jK>?7HtX|wi*IXw|2K6PEEh3|GdhmOC^!; zS>=OaN<)!;QbCAzgd;AUyhjjo!&Eyiw0kv&u?&2HRYa07P`mt(45EL1C>K%&Ds*K6 zDqgFeaeB1Cz+!F6N%GEkU?b)`N^>?(>E?Aq3Hhy3v5g^3q9=KUFt&rF>Kc8m( zI>&=;?P3fh5N_?UKGJ=x7E8*y;J(HvTZjGtG#OSDq@=7ufhiOQ{$Ac0TfzR95z$cP z+3O(#^nqX=(sXFYUcR5|@Mxc6d3%2ySFqjH@rxKAJRjQDoWkV}%L@K)JT2GKoE?fW zT*u#`*M~e2?imNS14;rW%wP4D*oS+`@@dl6Xz4BHR262xNxL&T?MWU?`BZ8Q$pKYy~ zr8?e7#+&Flue;LiWgVn-@bZE2c_oe8iBeJNntdN*G?`0@N}%;axW>lHgyDgHQ$ZRx z&3Osmiu2M7thIbF_raw}uFz-yB0_~pIWMYz)3k~8vm?oVuxoh@ZZ#AMREoq?w*kTq z)9ML3@R;w29{laWNLByzV^`g!oX+1u&rv?!e9xHB?Z51FO2Hm{xJWw5?bXxo-tZ56 zR11P~%$s(O2jmN-NMWht5@aC)b)kD^xBs|SW%;EZ9430NH!l3w@Z1!-fo)mK!XJEbhziM3`Q!ZZQ)$Epmj`A`8lA3Hwhl>iAesUwYwz4hph8lt;ny z&g958`l!`6oDtR6s-`(#6+w!V@x_56$SESm3%pMUn2d)K`MS7=p6~JFPE+ z4tXOWifegiZNIA{BD}(8>EXbn)1r>Pt>7!p3hA)GH{xXGQsWDq(Z@H*V?Tn)7WD<| zBD2{xs1#3#EbprH8OlBVtq$dI)Tk24Ov=>S4lqnxd%Rgm8 z3n|~5ufBp!|F1H3V?|;i=7brsFlQO`a-z|boz$m!2MxgeZCRG8j9y^c^QlbL0JN&V zKeQcm*RU)lAcGJuZQ-kUi6vha&L>l}eapW{8R~lR1MTRv`i9~d^c6`Dznz<;|>19jgd8NZ9;+BZtFJr48R=R=P;~wu+4(n=e zW}L|S*zf{rN_j8KIwI~)gv#@xk-G@Tb={umGnN!QnWP(zj&!&OcgC7)1<|wZovSN& zMNtAJ)Q&~Lshl4J@xi`rN2A}N)k8*}c8-J80^$*Deu;%{Vfq_mMn}8yh0w@Dq?i=d ziHYwI!^ts}?~*>>dC6v*9*yn3EfQO~@fJ{V;s!fGGjG|sOm%YLgF|+5 zQvmC*$CTz1X?>1@H$nStzruHI9pQkDTVWjaF!?(Le{RWFVf)`6exhv?l`*WHL;L_#eyA8zcNzS<{>~uB=l6lca6{;W*0LY@uBY8 zud1rc(DsFiW)4c2akum>RSjBEJ1R^!-GD@4RKY$w-tpLo%aNHS;)4ZCtshz;Px1<= zUu;90EZSuO@8s(1}HEIzq1H=g|tq%apDOd6QQVXOmftZoH7%>?H_+ANYKD8>7i%<<)m1c$^<_y0Ta00J{zAXKyS|3Pr_F}&8 z2@VzZGJns5{$O&Io}Fd%Ui^}NB&OD{xT`LB*r|r;8a4Gx)9Ve>izM%V_6SYn)25zY zzr(>Eod}kjm%ZKNaIM8SUvwz4Ju%4XWfd@Wx0FH_yK-JTDfshuz+FYBOwT5D?kD3H z8c*=;GGG4@VEfD~3G2^TZbK)?S(^raM&cDi=Rh34T+s5 z9Um#RK9cL1RWA&9JwvgqKzT?Qa4_D8(Fb?^rxo6Z=*N8oB}0!^06`&B7s6B2}1BrNWA zQg98mz+P9XjCFSJ~GlRU=)8$&N6mE~~`2xsh z+{)s+ZUNEdYsLnkeJrQ$e>tebcr;E%TOSqkD|cNmfl zx^~VsztZaZNx1)YEu#Y|SI8@BxsFZ^_ZL$^hRD+bdkmb{85NCO-R8pxZ_eT@NbHOp z9-z#N#A|g7mdhTUF_#5*Y0mMbbamSbu}Od(JCs+#dz+BFp4+>JO{fm3HnU9gaDbLB z4`QRf83M?{KZ~A0vC2=ddYPpLvDw1@PQL~AM=Se9(nl5(8QojAxvO?-j#IYc%;K}2 z6QZycHU+VlUio{5FCH&EXe8g}dPzapv5lf;KP3G) z2>AQgQ?y%QVBP(dsz3FMEW=S%jgtt;e*6q2&WJhVx>VO*X^inlesL(C+-UYRqe-~F zK*)_!9Z2^8CCqrYf42QZZDe#<+6!S;sVJW9j==Ix!nmEdGc}>s)Kz@>Eusl-n*o6; z^FR;0rz?P`WsAxZ2@hRgt{Q@gCfGW$0t3qvN zFh1eistQxCUe^k2Di%?zGXJ(skYMpliSJt%c{mEahkmWUY4+O#h4)vw_+$y=lz}%v zk}!4jeIQFe@YHD_Ju9k0Qm40wTy)U@36Mq5VOV+PGCJ?#WoCY<80-O9Vgxp1hLVY8P+dJ`I7W>X;z2Y!2_sKmKed&T-kd9x5s4{r1nZ$`8S#EV3QX$sCiZ91q zu`1Mow+LJx;;_lp2wn0*8=(0<%ltwzC%(V%7J(i71)4*&u&0OIwxR&pi}kvAm|WkD zo9Q;lmD}n<@W4@K@dljC50U>IdvMw&i97w+i<998Po0qtwbNr651!7gSh#YKh$cDW z8D8#VKMhjhOo#FDue5=^Zn}pUG^?{APPSF zeCqI&*4M?DeSdPNjbDE(480bm#Q)l5+WxWMQWgGgT&8$NW5BL-5Yt5{k&{C$yZ+mdS^AyPZ$Pg$2;I|Vb- zz-k^2DG`}X?OHEo5O(P>2&^${k4eouB@Urt{LQBK88wbgdb1e)qITcwWyaa=34sBj zRq)EmhC*5eos=zpsNTX5fKDPj!Rd}JkZT=Cmq21a?J#Ahf{8R;=oYjWlZ*KZIk{{{*poPz;q z6qW@~`MG~YU~`UgTy+BO2^_t92~>U~dOS*(1rl|R+E6>m@|-wAtt!(gxHp_th1Y1) zeV-xO5{Jz^Ed@CuN3n%TvlV>o!x~82p@qlSZ>sn5**7=SPj*ApObF=8KW(~)pl{+R z+wg}a@i8D$)?4%twsepbyhapw3PS{ z8U!)tlLRMU$Nt)-1AlKIgVX2xU6?Q&wz(Nsu66(262SeY z%)cX+98^5M`o!Q7FadTMkWa(S7t9XC6EOnMtcp&tV)zGBFMv}+?s`t1xHQd)xlw6< zBh+)7 zZafeHOOw4|*JO40rD=eHKahJqHQ?s!@WC$2*sPd~ZiTDe=O3No4$OXJ4^6Rwv3lj` zo4sOa&QwN-f})Akupex3}>=1V4eM68BN16`X)MK;md_JH0Qx%r^MqB@QO{l z9p1J@{xV``01#!ZVK~4?w;%Ls>s17$@nWYS9}6$Jbg0WBn*9Pd#+8`4k%$UiLQ0LT z26RK{{i>-@>x1?%mVsGVV}H-&G;dY!kWqo${wSgn5F9cP`&<7~9w7C!X()h&gARPV z!V_*IQsbucrG;s>y4H7K_HLISk#XyKhz2M> z%zQa%$GsGUM`g6e|Gw^QOgC*>Q(fWMtm^;4fW8LnvG@bokb2=TZxoa7Zz-maVyO;a z;LDXmncR@i;iz!+0=T9J2>1Bn}PX=81@R(hA(Lo{wTZHSOA%2c><(gpl@$rN*D9hNpE?p$5T< z)+?OBA`H_EuuXh>-*VxEz}G@ionj=mkcw8#=6B4J%iyKkyBxD#-7DRPzCR^`xk4To zb6RA$r|?HBC|j*nJ-~ry`J?r&P?1<{<}q>j0&Kv&$vOwNUz*XJMJn=I%1&sH3#CZT z$9P;!W@`K`#AsBZF92L@lr`kkYWr>L_rRsDP1;qY2oXMhH&Cz6IN>uY+jwZ9HSgsO zTVDT(x+tCbghWGLChz$C|Dv7>{Xpb~Q1sSuFKSzL?~?+hC=<1ewWDvuezIgoH8x*s z`$)!=!m%npg@XH`-Tz$acX%g_EILVB+i>Ys zCoP%w(8=T+m*V<#_S`ZR&wt6 ze|$~@-o2FKFdW1k;moC8G{fyYknNH!XqX{ z%P0%KBEZ5qpYO6iU0zh75-DSc$a8lD`m?Opo-X>>i#CHs{vkiZj%Q;Sx|P&WkHlIem++VEIqL}= zp>(pWt!dPuHj(r$J`Su*iN=t@`$tf)*cAky9GH6_X?kjynHz)2KLv$#s1-ek&j_b2 zkW+GRovwa3(0p~LUakENZ05b%l$|Tse(mIXnlp1tiP)15*D(S71#k4C(!4vw`GXGs zP40X=>DkE=3Hy1lcT*9#Yg#frpYl~b_6xOYUc3Wm*D%uC6FylN;ZcX*0n8KU>K|+#3M~#@4P?ZY(tx9cRxVj7^{)03v zh%KC+zQ~-Lgqe?tjBo+cv`(DT)D1tNK+hg+6{|V)oV>VL8RvFxyw-69r1dJWK z0A>Jz z!D0QpPWw$ryjXX0D#x3QFP{&WdLKf)NU>RWf8t&E@b^rH1`aAdE0k|b9HwMHzRkSi zF%$s3mAuPZV4${S36dPioUhQ}tOVw*fe$>%wR1W4wjs?uhWvqx_4BDrQq;S{N5u+g z>5WlEuAGozF8|m#w28M%<)?7DBAQ46eb1v=0M2aNx6|zS$tKsZs?a$2Gyc{sa%uMh zZd4+$7*)sD(|$BEiV_T&192x^Y=X=U;wlPGG~J8qjntLNipfeyyE2>D7hXOvwgcCv zJa=9VvMv_IEZtxS@8+Sbs0W5sn7vZ2{`=FIk7T{2vSt2GZ9n%nwK;pg3xd}XaQS&4 zajH<1-Ymu>b7R>!z`9HU8~cuyIV{;<-fhiQGqDhbs;ubF6^x~Li9;R+Sd1hHG7>0F zu&Cx#&OtI>IlzfW@gr__t-tr>zOQkTfmdl|vh^!U{O5k{cZ+MG?y)uVs~oU*W119f zN8;>Qg#c9sQ4n<2pfW6!mLE(sGdAAchD%9MuCKocx|2`Qx6a6&Zop+8N#T;?N2#FoLK0)8%o0 zeAH14+|S}pzfx$KKJ$SJzgB?LfbRPTa?epLPr?)zy02Hzu|))7s~bzVz#iOe0zeOAzew(}Rk(DKKowJ;Bu98QEe)^z{n3m3Yk zKl2cd9g~+MYcWE_T37JZ+JNSqqUeC^noE+xSncQ}KY2KCKFimLF3V1^x5QOg*H$|> z`*EYeOmbnP9FT@WY*!3zOyoa4!yRz)h1z9;&G*1n=ItECT?NXvLThL~Vl+2lz)4Gm zXtez6jITcnu;=Z zojX&_W2@&DY$?GIrD(8AVW0cmYzxHJxgtv&N_cfbE0jRa?dXahz?90+jamtdCa@&n z*#2veb_JJBR*$H|G4rmC7RwyAZv+5F*o zx^^}CU{(_afrU3Y4s(i2i}Sd_OGL2&(>{bg0d7a^q#qLjr|V&p(DKcbwuwX7WyuEp zDwjTyv(>ABv){UCa&3@@eQvG8jTKr2A63O1aLyp&C7gKlZnZja25R0g>tR!ohzRtDp?AmRN_r$& zl6j>K=`wfhU*)7+T9o)ks%D^~PO|byn1hHR=!n2>wkEo>%WD`=ugIczy!|h0zpFkP zdx+~BYoHDs!K(FNzWl0-;$=hpvZwvO&UFT<=l-)}DRq!yj$o{tUzCxm(;@u>pkN$`{tqtR$qSxo_Kj#?%n{g=cVeJ;b2 z=K*I1xmI7-_l~qHEzM7Pn@C@XzaCcw+_V8F;s4~D*G@Y1GfC8~B@IjG$Ts|Qieu0_?4IjrMS6Atth`g3b@PMWC(JK&&nQa@ zd7GdrlmGNJBuQhqNjg;s#~rykU^Og$V^=-k#6W0TCB~dXf?B4uBG}z_lK$ZN$fD-! z=<3Gd4^>4}7*F%lT+_9K0F`;oa7M}IGQ|dFJ}}YFd{5DKXD|od6q`o$))Y<{cq15I z<)4cFzQfg8*WAz>sexXgFowndWMd;CLOI8UJL238rnU_m%j8W#NcO=Kn? zGjjssX{Qtxd}*yNvdrn5hqr8a7)<9IF@ORN%qQ5WKV$1O;4mJPg}E4{{~Uh3CNhJs z|4mqJ_|vRJYzpFE)Q?Jd|JIH4u^|-}4w}b7vsnyHgB!cMaIp9D2F8hxh3ecC?>DU2 znpb#=)2nCgOb+=LHddp(y4RT$msOPJ1{)f%V(1~>3pj+N5wa|-}Axc!LQ&jviA8{T2r^r z21Y@50avl5EjQPfuA}un8P;*IH^EjbtjJYz9v4|dxOY#Ukj+)18$gkE^$#iZ8D3YY zq|Lt?mf$(^wv;Pk$j1<8yxX*_$y%?MQHYFc) zD;#N>x{4?2-n$g~3<|u<3jRrYbsUtXNrHypr>!dE#Mk;$BbzR6kAp?qg*VYcz$2e` zsCW~OXN}R@bn2s1k0{;N+Y*Ta93CZbxW4s@5qBTWDFc+f-M_@jH_h0bmcsLc%vCjC1p2>XBfDW?%}%XxWL62G(P85UD|Mk#|!eL$+DRj?!#OkeVQ+ z&M=O&t||z5Usa1vR7hs_6;n6dfXUZc&X60+31xaM%9(7T&w*A~{8Zr;stfYO>Dj&a z64Ts)3I7R2VDH0?-QRD;E@fgkaTTR*lne8~y@CGu3pk7i+8O^fmZSDq%P|FF0>xOa zLKD|T_6GJ6I)tzJLo^9?d{Z#{ooYwKU^>a`Wy$sHFZ2f3($6=1@}2z=_1=kkQI^_j zFe0!1mp`YH)|gISmzkeU{3rs9HMW>l+RYrn**#5h3Y|W+8mbJtVE1N0X2mDqj@roc z)&Ly;4S?ONxnW&v>h%JB{M?1^yJa#N`kist2ZQfQCXUf|e@VZM9zM zBr+V6BRq$ySY57s{z|oZIpnC}6m%D_i`sx>z)6_s{e_h5Ao*)wKA9k3NcbE+T#I=r z+(~{cPLsqD(I*eVTgyIO)@|ga%SQBNwEy#>*A& zC4H#uJNV{#M;ufzAW*^6W!F4@x$PV1yhq4CV^$YY3Lq3DIWv8mRPgJX&l3&Ro98PfEQE{LWvXA7WKkl$f^ZMbQF-Bu{&F7%Xq zG~S79MkP-8N(3M${%Ng@-@5pBhrELI1Ys?z;x{RT0qlqh8!FgPY6k_5W;q7XSfqo z&jW%ssHqKwy(H>1$cEywkvMWq1XdM#OOz?>V`0lEkOkHsihaFDr~UPk6Xs;k`hIt2 ziZ8A+?lHz56cAfDMUqO#d)JV)r=O&m{L^Nf%2Wtt3DR#i)i>F!~kg4m@gU0YK1<*=_GCghTPjv*yZnQ5- z&i5e}3AqU@em!7FyxeDp2*$UWuF6#HfU%rih-%neTQP>)MJ|xIOz0zBjf~I~samwj z$!+xdP>?Hw#%6tSi`?;I)pBMAgWaaslKo{G+OTN>%F#tBu-~J&n-XvqT4>4($e!d0 z9{T9Y)h*alr>9O*dG&D53OX*^tC0-Lzj7QVg~?@l9A_26=5Q$m)tK%+ju&eEljcT{ z6+rlbg?yHP%Ey2^T|QFu$ZL2Q!)?0Z3Tn0VR!lAZ5e)dt`28tj;Z0Rr&|J#dTWiXgt z);4J{v2md5&K{1^iJWPl8v&P)K~BCBGfD$=o*M`F<8Td-9xTh)P%5KrAL3=AKVQ1u z*FNEuQrz))tI_6}{KY40%-JFbldL)tc%;>53dNuf#A9yB@P5EE*XYwpy6fWr{NgCk z@c{0OxA^NW-w>(PalOOa#QUeRewZiObcQgr%rSt#3Svnav3f=ecPWrJV1;Yl51@~-wNkr zpNG&UU_QdW{663t0v96)pnUr0#8?~?DmS!jn=9zfRoXMJw+5AiWM=YGw=}IVH>&&c zS;buCGd_Nyb}BZD{xll9yc?|KH38TGY7?QXO$A~v`KpBI&GXSpo- z4g9z%lC%nF3kv??#V!Zk+U|dH_-?|SsIyRgBmlo-GYD#&@8d!~_YzQ%UP7eqFafJ4 zISHEb6D3l&|B53+1}?5m4&#=GKFS189&FpQRgwF{xUqm2CRfVDxJbF!FdSs^WSR)- zu#qXQ8r3v5pnQnx^k9<1B))7;9WIhQEixunAd(r(Yp!g^)f2TLbfaInu%-47E)7G% zj-5sv6bGuFd1%R20C~MM(_M}1Ea};MjK^W8B#r#A+M?26`a_3|=sp`dLa=fm5Y6cSBpK@UpJ=51R z$~Ms*e&DlkVzJ?K6o|w4i_Mg+?SD!9z7$+m%`~Bv@pBW1%sE;~6f=q08{4d0_u5v= zjR%x|s<<+`pQFNNeq8U%?ZbG8Y_?jzL$eDClVylHDP$=8vo80iRY69(D~>fsFgVCV zyeyKpnrP_-9B(HK5*-Xm#a)?4G>^YC?iXHr#H_DNIHi;`caOM!e8fO!s5m;nN`0t?9dtE5fYp!MGbV9>L!!}# z6&_c*8E#dhs!NdNo=ndZ1&et!gQqPD$~e1 zbuzw|^(Vvos6w(b+04x}@LPA>s9c(*gdfk`F34kP>lr0VFZExA%JhFU;WhNjRVeXR zB_3awrn#|B4W=<$$UgqG+6njZgL9TngkM;MNY+2~4WA&>X44E7q3!*};y(Q^^Nl|@ z%^Tk%I+*0w8jG*)kC*B|q&gR0lT0nPqn$Ms3&GSrAC+tNSys1JdNcZzLomC{Gg5=R z^-9Y}b!_81?B8Ol$GAn$c88aG4;t7O1}VXYxFP#7#~;^*mni?Qv-b>ZqFcX*Cked^ zND(EVR1v|7N=X0}J6KVXqNu2-phy$QgpQyT3)mol1rY>AnzV!(iUMK*r6e=~DM@Gv z5R(56V0oT%e&@Ze*Dqdva5A&^p1Z7jtuyf{gt(4Dy-MO%}i*0u0; z(!N}xFZVk8aW%6q`hz%epONvJpI4mp==%hGBjB~*TkgD2S+UpI<`cJ7&pa;%)MU&^ zD5dGjMD$VQQ9!<6-fCJ06^+8sec}xgx*n3Uj&R7Z*`o(i9RUBI&?6=k52CnZKW#=F z{f1-VR>68`j4%cexuefq>+MY-hco4|BuNfiV5!N2SxQ8=Q%1fy*7}>2!+bfk$lwEa zD~9dc`^lO&7VEsiyi@^rxt=F}oXFO0u6u%@YOpV%u-nAP9~4HCXkYx=nkoiRfD1W? zMa?rym~`e(gL*PH847yb%}C}=?i}(ZL6iv3~p{yL~=$2mTr!3 zSB0YZmTqsuo&p?IEfswrJ%3H~s@?DG98ckiPv?vt5|BX*?wV_Iha;xsC*5JBkhsjKX zovSAgqM_HLi|)}IMO!;r-*mcCYWhRWNo$Rm4|^$3IJpVd1ji? zC$}DwrLMs9v)^dhL1Dcgpy+(5XbA+1ie7}vH`uN5tCxQ}Q0+wIDAJ_S(hiTe-hb3JWN(mqCX zrMzc(P+2qjmCKNF$JymK=kBAM&UNl{lQqmtS<9ZOzv!+fCCeZudvVZp1O#@}6>Vg! zQbud=Td(h*pu@w+^5&=(SC?{g$z!>adJ+{W%-N*Q_QzhyiR}kmSo!UgFC)Ql!k6l$ zqXuMvtW>Y`qDHk+&j~)3XyJCu=+9UyCG}@C`b#pM^_3hx2#a2`dgc;5UF8vU-P53 z6$m-*`sE;;U-{Hx47)(CC7C88{NMvAdptO3?j@1Xt;3pxMX{&tzwrctIrdsK@^Sr$w?kn~p5(H{6cb-W$qd58rdvdzmpZLm9 z&WyW%&Hb6SvrIQ9w{lg;(lp{YG%je!}6m|~2n`0}Tk%9M+0G#2K6N{~BT*+#Cznz&4tyT$&pttDyD4A?v z-0Kx|_$=ex3AkEw0A|J`Jh54`s-m-la@pTj@GbG_dI^Ll_pFR;=$eIocm;I^uzFU2 zmTQrL?w17k6pg!B>yZkEYriog2E&a)krK}(aLHRLA^e1-m%bH~@u6&{iU;w_@u*`5 zaox1c8Tv|AUg4w85=;p~x7Bj%Wn=b>OJ4qzvU`Fj$L~0IMl?mR%|a*<;J{I;SKgmU z+q>-Q7Kery(UBN@b_j%=Q|f;lQI$v$tm z-oQ9$nekj3VP3DK{ zCDVdE1zrzwVV&=N+&4u^kchfGvg<9KkZhYGyo77s;9fp$4aBF3PMxvJh~c|VR>YWxA#?Je7;e@0@!hky%Xg!$^5j$frIYAr^pk< zUm02!M19OrYNw|LzR9tmGWcCegPgvWQ}(9&ul9OjKjjJo)~~4@U|-IfliC|Dh1iB> z!6#LeH|!KcXahV5AZdU}1h}#I6doiL_UQTBK3?~VVV0~r4xk@^$83_NI=?z+b+@)0 zfyFIJ)HIRDUX@L3c${Okc1b2GY;3;8|3%vbo$3^w8JZ$^nfq}itH!yIdJm|gew2>I z;}pEOweBtS$@8pB!^)s2T1J0X7-yEJ8sSowX$7wNwKm-pI9^8pa!IbY+oP9#rs%Ba?J3H}#$v4}+Rg6RGkN~N~XDu;j4#87$0 z`O?ZZ^w^nAT@S@AP6A562-a11IUv1f%Ag+<0`;m_@kF%GVy?N~5FU1M%8_GQM zn-`Q!N;_mkcfUXWzChxg26a3*O`oiYEa;AbkR_G&8$KBWjVZOBe`GBY1U{CV3`MY< zV11~W%ZwwSu)*y0*t{!yo1Q>kh7PUgp@kl#;P8HGARzShplmgfg}Y1urTBH)XJt5} zVGnp;EHgt1tG^FR@a;Z=4tcIiD;+79r#5|2>T>q`YS30lbe-CA5oRv^yrsN0`EY34 zGjFut8BMWS#)baF`*)tST>M)qCF>C{LOU*W5SObAMyK~D49)6^u=sQCDdTHsEhXf_ z8}@t6S94e!8XvL7k z)OOKwv<+&OTp^P;cmqs20O~c*qzbtFJ>CBDwK#E(eqGvjyMpWO%dpp@SMV?%9yb5$ z1>G$V%U|iE6f^Jk^2CKt24x5l-W1oJm1k-)AelZN&v%Ys13| zYv$=rTd!DOfb5gT*3?;4P$S+xq(-7&1t=1~i&?H};U~H~;4W2~zG(M)Z+s!qCI`i? ztCJwT{o+IIjPodaN^rru;9!2=%g2rHijyNI<%H+tmH*5@%X80Eyt#Pf$ID|C>F<&ML^xsW$pAx~!e-HNHW#o7{G)vT*feJDNp( z`NlHcKdUse(E7Pd_1@(mG<&7U%oj}xbVt^NoMa4|LvCx(ETI`N>iwIS7qc^o`}Co< zAWB-}w{p!C#1BnDypO>SZcz{Irwuqp2&by@EJ0tznD(jq~V)?%MX#@dzvRz zI+jHblXrDX>362)SZ%DBdeBkN`%iW^5k~D`ssUP`*OTlwt38W;m~>ih1v8GGGc^q# zmEre()AkiE+_733P~XYr8*}XZ`d+PI`83;NyJ^eCY^a8S@RW z8q4RF&(*zGg{nC*_$wG&apO;lbFuzcR}4l&NA#%^q%>|#Csz%8N@cY3C!ARX@Gm4F z8(jPuUU42j1%NR1z{2wjKc@W%v?n}j)x$ZS)f|Nx0ROlDDO?v}7gu^~7!}vsu6ey8 zlJBPXsSV>x3U*Ij~BZhb6}2zvtXGx?gv6S_b5ja5?T+wqjW1h zuw)E4w-jIBb5!7hC#qr&p8>o{wf+JCl8(*|x)x?Myj2H24Zj7s;o$LoeK&wObMb2w zA2mc?U{X1Ehu_>i{7T7klL?q3uFYj&34FRcVF6go9y8iY$Ha0`_@VVAD@r@Gr`RbY zMEZnm7~X{u_s@wW;0^6$3)6W_+IhzC^BZuh6usqwm!myd3?Y+n{E3Geeh%K>$LFU9 z@>eP&B|k05nY&w(YY0ce4V~O(itn1tNzR)hG$bu4m<%}ocWm0yINJd2eM~uD12V<5 zvK$Y~{+}$Y8P>Xa+Wvg_0MsFKcJYYs3;vBnw=IKtLR}j-e2IZT4n=t_D*wLf0HLbUf2_Ns-MM%tB%LbR0kvZ|JlPRMOXyht^~F7=xnHqv0=t?ce9Cse&>X zDQM$xXC2@D)m?Y%J!mc)%?aU^plPF%U1=o^GL>xXwrSn$jn&BFj1Wei7;4blZQQupNN^!t{J}vOVKqa>KE2 zXSo*weYPZ)(>3RUOPws+E`OzlKP8Vz`7&kPOXsE;0kMjE_+0(+b4|&&;-B^v#C9G* z5e;6Pzd6fC)D~mzVDendoXEvRXQF#tnSwL+>D?hP730Y7;06zMTe=3?3D=2B8 z7NDb<>rKn6o+N)%q|i?uz+4N#;}*9`k*M(tC;34LCG8wt8g$%*0Ud~_C&49hsv;uM zQ=TmJ;Cd9KQARs#^wRF?8WjotM~T;@69mGZMS_M7Oq#)DA27Ccg#owOV}a}k-lI9; zkK2Mg`V0cjG;+P+C?c$xG7tv^b60y9MvlYbAy*9#LlIQYS77h)+-?2GHC$`}pm$eRL z>A9xw6^g->MA#Euv@4p=a(9phz_(QUA}9ewLRbolXAv@o$^cD3$RMZNu0)8K$F$$_ zJklSts3fv4rhjug(y8TYnJf$qtG#9^!dp_PNDBBZCvOwj45f84GY=6Zg%sn}`<6 z*)8^dW5GooGvqB4$V$~vL@Mz1$B7yn69kGD` zkP$m7#C3O(S#=_2R+UVYZQaxnolVw>Bk5O_^Ozjan>L^$bo$ zPaOhOEfI#WKPWZY$s5cl@7VjHA_Xb5%GUkXx{p|zbIQhp(m>|e|B@#q#WpNHwm^bg zKJWGt%3zj#Lf9v?Lhwt9&XRb>r8>iulNFZ7wMS3z&5CtfHa0-)8rMz&VABY*4Vauq zosO(rG0sRQ*N6fhw-*4T_oKRK%KQq-p&g*ZY?Ulvx&Pg(hh<#=zJM+gl7li+#6 zO#i#(5t!{j4D9gBF#@zbY5gGZs5=RHUGnzG6ea}+;10i23Lo*h6`;4B+MoioDj0L1 z{(4t%xT0N<9Y%M|r%Q5*g^2Q;yshokL@=DD+KPcsjiz559qk!I0L{pRCub=)0g1i~ zL?XXgdDUG!iQ{iwlTat^@LC6dp9t#i-IU;qCg!iNPN?R)n~`i0e6x`xg1_NYdXmYR z?jCT`%P?O4i9*EIJl9?#yM)z{22>6=HXyV(M;X=MD@I9R`HP*>uXcbp!S2X{?D4;_ zsy#tY0R;Umy0gdd(YwM1@f&o>I=&h7^@pkQg{D09u{he|a zRZ-ID_03d*)8{k8a;0N&8Kvtoi90)Kd@T948$R4yd^m0gTx!c|u@A?DWPVFtJas%p z8IqPqfdSg>kK$G)I#baq8b)STYqJteF=qe4jRKX~Kb&Jw>|%iJz8&n;yXDjQM2sMr z&*-$E_e~dz068xlfIHjCT&XA*X!1#2l>7doyQO%(OC2?eyDwR0>IC><{h|p=AdjjD z_J6JxCkXrpn8%?3UMdF~#|6g!s1ndc{u1JVD8(Z-zZg8?N_M789(>t(@5g&(;e3x- zbC%z*As8@#+B>pijC{uD$~OwBn5$ivbS}E*E2hs;c2nlzYm~O5TcH|Kke;YD@YRpxLRrdL~mvP`A-(z6vqU?9xC#4Ks zKEq*%z>9F6GL$%$wB1N-;pCa z?w%ie&A-fF>Kxg{7EHNK1m@Vm3sgOEpLJI~Nk2UIl{Z=(@mR?|I5KN#C$O#Fna>~d zjv2-E3*Xq|;{m;(w@dGk=+%rw=6mw#qo5EAp>T`O+fndu>ga-QjaMi9rEc1S;Mmzd z#ta(zu32?#@yJ0w#&iI`?o4NQzM8&2CJ;b!Z$mL(FL|B7^^OK~4rAnmR&zg}S^NMiQ5h=AVV z%6(SfKu+T^x+jyP^Rl;(||xyui#k9XX}Vz|%KY&`KTkP6$6ilRyV;NeGKJ?8kwQ3DToCqE0de$ zGi{wc|0Dhuh{wA$*VjcMH^Gs+`MN8E_&6YJ&b5eubCh}tsPh0!ss^+aKrZ$x+{?ka zWv%wX)^Wq3?VN1KIYhSb5Y9mLb0TC0wkrTAiLpnUTyN zCEnR;#!!Z?To|V~O41fKi)ehAw zbdpYX@An#{dT+WiDFUXrAN-mqm37UX0MHx3zaAL=L=VJV3MMMr3LgVrU@Rvu$bn9F zV|v+RMtURYdBd|&FZY&UfOlfw&4!>w;{AJov6vQJi_}Pc0_A~4s1uYIi?CrIoHH)? zXL&CNzbY|GQC7y`l#D3(@?FjnrJ{Rhs4?;#_{;{EfF@H>|1#e2v2Gjt4N$qY8T&5c zJo4dw@b}@eDzJnMhiO?1%98ZeG#&=sl>-sc{X) z`kv6Qw0kdDZ~;`Bf7uUs9|H>qfGJa8E60=G@VKGd<|blaljx4xK;&@QN=Y$giGqW^!7c1o4N&Gxt8Oa{?OcOV{_tQRKYpj32cvMryO=;En%6vOor( zXPW;#3)s)oP`UHBkI_bEC8J`PV`T)#q_OWi?I?!c9*|Xap^8-nC2*;=(B0J%K_EsE zo#BeK0 zb9WhZXbjD-5;~fecy8+@svGik!l&bRXoRhEQ2QVEj`{BWFS`yP8(ZKPf$kJx_#O}i z%(=Y>V`au$AAS>Q52>U&j*y?yq6le&wv%O;W5DcA>x!vLCFRl%v4UGwqR7B~{9c~? zETBx~J;;v&P_)lINW!4TfA}J%R1!)JZ_Xo^pLs#jssdf!i#sDZQ%XOHwWWF80=v!G zC$~AXwafXPZp<=h{mS$mc2Zhhgmj0aOLu9m22!Q6Qim1erDp;{S1R+X{7ZY#i}^cC z&GD)M$y1%pz~N4O0SKumH^Zy?b`SX(Eed1k>nCkbzGMJA>&}kw`+M1_tOK?zD=s9_ z9s>!DopH)5S9$5>)D&^dy#L599v!vO4HV*kSElpQ3f>Ssv@Gg8HOk(lF$p$WiMO6D zq{xqP6gVZVt(*Yx8>SC)&8(;A6GWf-;_vkX(nB&;=r6hbWTh-_JG zwLV#3`h)FmDzn-7y9o2a=Ydj}FbrZ|r#IJ@{h#S#J%cPd9dLQ7yfo2g+lFgXxjhM7 z7d6RQ$+vm4sX*lroJn>cR(G!dVTW>Ys0*Xv!% zk@WaGF;=C-qG|CQ z)p%N1fN9TZqUV8uKZ~|Z1oJ$CD3ffru_OjhlO!Ok6PT7=Q3NIX%%LQBb_kL>aN{6? zeI63i6B*i^6I@A2Ye?T#6m5I>yG-p^*o!TKLhA_?FnGrwkPa z%$YG80C&UBDcg(@y-THU)|lNYG25EP*$Yxr7(aOb9_K4VG_HInv)Si*+Sr>5zWttj z90k;zZviNNc%!wyrFQd!^HTF(gKVx-stGHiXb>$cvTAn8Wt@R>1NtF({e#~PU+m?3z zmA^Tb=snmjDk$2%Ex`A6+V=lZC-Y=B;APYTxVCLP?Bg4hDO7?vF)T^oyU#Kb<50X1 zbk7Q~``}ESeo=um730*fhJNaIsdrF^ zLm@DFo+t2!t8o-S;6m{VHlC5&pMWR__c?tMm!H|`k1^@ZY@ZPUMK9iP>tqqkyLjN@ zBPwlKHq+Ag_MQ*`)u0o@MG5)*RnRGBJ%k=V@tZsS->b7j407x2u8_n0COv|K#;M=@ zY_vK1Sd<&aG_)Phd1GW65@QdCKt)=v$`S}!I5XkkffKSkQ_6W~0$y?c&m9KRzJ>hr zpo<37X;gLXOcptUZ68&IxEUA0ryP>8 z0smT(xf=GLOXAT$@urj^G7Cc|w$W!h*ODsDbpjclB`&_hGWIr?20&rCYO(K1hZ{3> zxB6yKp?L4X#ES>s7QRfZBt-CVmA_1h|19)kI2}w5tTt|}T+Cf}q`(p(Rz{gU3f6f$ zcvWMsTJpa($4XyK>5B1kBE9U1NBDx}4r~(saHBUs_#bT|&wZNbtvjcKUnpqYwb)0O zuspAD_7+6#dh?$4{z(7kl7SyHJL$BaY-WJylN*_-x#Mq9*p201X1|Lg48Sol$^BS7 zYZ*kGm3l3=i>w!nWGnDZCC=Lm{Cnc?oA?|tnt)kNJ-DSH5^qT-G~Q*|ondt+fu=gO zv5W8qB!pg(kn6kI2iV268oGhFv9F6*v+tbwHkAiVOObd0)Z9qre-vd+By?sMd17W8 zy|tH0aqeoWU@i$FjujtguLIuDTM{d#A>ajUtf?njq)fu_<PqluEMRSMpR;y{(p(7|Rg#4=8^@+W_K-L@;`{Ae=I?BJE(tXtUFC(Q9d8 z>K&Rwa8Vb*yEr?T0G@j-vmQ?!M6{_oWPO*Su9m$!0+AN*w7(4Df5$+%0b@8tIlqJ} z#?KB-sY1g}HG@xe9f38}lX9|PT?k(7NB(wfrnWBMtVeq>FxgBGSnet0@E;GIeX+}O zp5`_;r(Ni}J~KR-Y^QWJDiG#Oi}bHa-oh|Ju(}%_6`6cr3tGFYi2*0Qd=g!RRQeb) z=J=m6_)|sgRy^CS`KZnFKwdC(`$xmwRDsT%viNw{dE$_9?!yG;9St4f z%80!xbo8+Ta{Fhj%RNz4ylNsjUn8I>{a0E0ADeWS$;Nm*65u?MWuU`YtvVbxRUl}0 z4K6=zPU_129)drg8j8ocNn0+GeIsA@*I4M!6V|dki@P^yDK$qgfs4M|F9H^&g8`Ko zPY_%qty@NRkoK}FRTJ}*mt5Z~;pG7(XyhBN;iI;8%C0U$pZ~v0x>z}mXd8Lr`SFhC z;s*HittFg#crdtpXfgL4XhfGceprE!<>tByfvJvN+gsFamd^wsuR{@eJW&dB)`a?h zl<``$DS64%YYZ}ZGMqY7zL-NtVCA^|z&$7|h|72(j`%Vh3L&__62voenbwje5gR#t zUI1uWFf#wsh+SYSzAj%S&Mv(5BBY~!Ff^?AC>S^=6^`Y~anAu1LFm~QKI#}$tFiIm z_=7f8lI<3+o#XVm4;cW8&)=F)fI@BHC@MpH7@i&S4c*;##o$^~*^4i*3@OA)OdiPV zh=hQ22=7F$-*mnfDhh~9Jcs*#*}DElxCX6QYs}e&ZJY~TNhTsJ=EIgDJ2VwXl;akG ziT9!p%a9@Z=6G7Ni5TdQmgRjep0*FcbZo{?#J{aFcE_XRKw5>+vVp++24q5B{W|xl z2QZ=I^I5|)*8!p#>Vjxy+m!}1ji$GxsHK=}ACw^KBDm_RoqZe4K#FUf2zi>U;>7TN zGs89Cbqkh6)O8Z-Uz59N`uz!AQ2A4e+^sgAe=x?7iIUZzdd^p8|D_ZGZ);!EC9kE| zx!lS6Ys4Fl1LfAysMsRfkG2mpyYbXbxod*du`N5xHpH7FTUO>3wY`qQm5IGewAqP3QrVB>0ZiU3QNLWyLC zDfXeTP$gR5V`SS}crf$Cl)*Z;?!cvLcMH`M`Rs#K$Fj6)Y!sxUw%zC`i}qS|7tYaQ zpmZ5WukYt*wV4kpzhvDTGH;TZjZ9#bb8$9P+?ZN|4%aRKfkij2T~#dwuiJ!i_%SV* zDk}60y|%A}Ph<7)F4Io`TKkveJv|_byl`s&4ruq30I-7QF!U$DQvj@{G?+m25+;Jpw zpFBlh9byt^V@cm*DbiNpn}<@@kKOGV(?6{oC|w-<_iv4VuSGAOxz%YBGGzWEgBVwa z^?tQ&)RV9#D`?LQQv>{lFdrh#=IRO81oqp*?8d05r&P%R$!9M9>4+@B{M=Yy<&gJv ziF_0Z^PV+YA9>3ZJenz|j!RTm-rZ0`@ssFw%H8@isbBZ(iD>=n)90s;R*q(7(sxko zLcsbgUxwUkiq+zt)zBlx$YEuoBbzc+U$=jcRKhRNQu8AV5u^N!|Et$9$uY9iJnryR5OMkv!iV>$Jz#)2q3 z?(FcfwLy1_RcEEfIhMA5k5&bll58J+dxX2L5-zE8k9gbHPz(s9cbZ6=cfGOVd`Wsr zNK#j>^AAT~(}Infzo!b;R7}+i%p}&rlizJ>q_a=xSaK*QvuRs=*fT=l6HyW?-QG~_ z@A6B>l+$}e_|VQt zai%-x&it-%xsVFSBzD@i8|ZU4$W1b%o|w=pB_(-8mI^wC`zosD^E2zwckXI1^ZT&@ z3PB%IPh@4!jM{&)kL0cVf(U z8^xj)WBRciuLP~}M;>b>)m^%d%(@wL?1o`4-GiI~$IsReMrq(98e$49MDv&SJBd3v ziubkk-KX|u(FfytDEAdzts^j}N4}<^tu}SU`~5{-sGW<|64!UY0ukVCh}D?4LE`2Ij{;gZ#jGbEXL!IxQ#uh zORPq{9h{*tcJG9{8kf6kM!%QB1xw@*(g?nsixOjmeuI|kww;&aee4gzU5-&o+zLX% zsKVWTU9lTvvnlHcX-uPZ)U%@;@R`@_7|fAbuYCtG#GmP9=)_tIf7dzTLtTKY18-{b z#5+LxREMjHpZOJ<@)V3`PK0yJzU4V`Chgba@}F(Q{@4AydcQXcMjIBkUx`6uqxIbx z!SDI3x*B3I9iKWk%q}yXmKT83+NJwXS7gQ+d>7Hw8;-3Nz<(R0`AN;MtbqEI(fpl; z-o}N11r}V1i(bKXS!$l5tmf8C(JswH1>>Hi803t*^%6#yN)+*@#FG$~52FW}V(m7P z>WB|MzHPYe%?y?aFIgtEq)M-7Pd45Bzipj+Z`55(_+)gIBtJ!BXyOUhYA42$GqPq- z=kZU27y6Kj?&l+UcaqSJ4HP?$V!!0-cyZP&TvHa`P*Xji3(poyVXTt#z~QUI)!NVR z+^$L0kfOr*vwc;ompcqUEkGAfC$+WuuPUwnd1t&Jgk?Te$Tj&nvO;cJe4`i?cB4Tc zI}R3DIs0+iz%%XiMrs~>d&QO60`9Z)5da zDvF)?k1)9OJ;kOx)8v{xd%L*PF8C?)bXw3PCx+l5^MPDhomb;Y5!M#t(|8GY;92Sr7L86Qnm z{{4~*>cT|{Cz*Nc{HAhjN{QB|^iKWk+Wi31%2byv-sbovs@vzms3zFV9omhnkJ_9+ zsFe79>Z|(1rlJDHYog}{Y?jUp?*%j@m$_6)dFIW(>Q@uH zJTn*FVd=+6cIh3Y3epWX{je68ralB2k0ZI5BiTc{c3&HA5)go%8XemR>5NGr@i)IW zIewEPAH6H=l$o5qOUSVUXFbPgLIYQjZ(S zDVVrUZaQY41B6YUdMLglk6&!SS$S6;bY#pvO6hA^gZisQ_uozLt5O(WOrNry*yczE{kp4 z&kcHaj%jkT4$ne1s1=th?e*R^5S9<%Jh^Yn2zP@KP^v(Uz{M$q*)FyR6z!i|`i78j z<9*Ce>oS8L%KNf-y_%sMCde?&HT@5UgGTlIrE%**iqf!ixhTtC2Yx#B<~X5p3ZoON#4MN-;w<$ceG=?J4m#GQr1-icDWmcit*IQ}0CUJ1GCi1`R@cZH->YyKe+s{xA zt+66ykyqU(v=L;1`3cl}F$6BOhg9ZX9}c+Yg~7yEO?Nf;8dF8|jIrhO%%T_xNEc_r zQB~M5^cJbt9>>^sz~*~nR|+T<<}>=PN?L~h%qjMe$J#46i;=kdvKSIANlU7Ew3yvn z8P%|La_U&S8kou<$y5SHpI61TZX9h!L3g!U(WerEe^P;Uh{+R@WQ^I)8(x{m(H zk+UW7u7qC6yF=z6FcR_x*;hcw8aZ<^KnM(kZ)Z(%k8UGA%e z%OZoYB`7etPF;%hv(S7hPXIYsQ~mw9472X^5__uWYvV+IdjUnmp#a2ZWtGlGQL<&>r&7I6~vX#wM51S(c?djve>px(;ab#Q1gU3<#J{y)A z6IDG4Ctt`}vriL2ERcA7G2L~Al>X_=^X+*SB5<3Zu%o)(7$0tMwGQMe4nqB4@*SvM zxCOo4!XJD)`Oh*|7cMMgWfyal>{hxGZP6E5&>&Ii3%>Dr;f4i%k~pxt@PMYud7M$4 z)z4*kW|iPuCE@V1;9HtzlhOiEPos(q|Hn0W$I$(&UOaWFBl62*9g>&)QQk6NfHj7OJ%=E9^#y`Tb7iU4+rhAS;g7vJGOe5g z&CgR$T<>H~)CGqZ7OZ$tL)WBO}-*OOK2XKpuTnkUrl7sg@bpad;n^N3kj0ncdLAQA^A$+)MQ4N>=_?3n ziY!;ybmWRYl!e$@ZIYNHrhQ(;)YKzDb&IGL_ek4Bq_V|IZpoo0N7(iVE6tM4vfX?} z^2;;R6VE?iQmRQz&&@bZz^rAs?nEK~v4% z#%8>1}pvj-cWEy$$^kq#{B%G8HQ-BiZe%#xT6Sk|pJsO0Pbxfd@7<$l)HnHW#{HddCTU{2k%94-rqtcApUh2fK)EXu7@D z4(`*GPoV7F-oSc~Kn6}9sFk!geU0zhG@ujL4BKakSXgqj4@@EgRmacngScZHPg>nf z*kETtK2Cha1=R_G!CPO9Bno57-P*<~PXv2spA`sju{bkod2r?&H;~?IBqV=Ab;tg) zsAwW3mvu0}s(wJTSO5hz8La;2=lkq4DK7|NWjgQPv=rvV|7LO&>+ogth4UO zXO_~+VZRd~D;7u-WlWAtjTv;*A&k}$i(+GnR_0J5mrr#&9bmY*N)DU>i&aw5Eb_F{ z<5+3@jaa`$IAmw6*s|LWP?Nv!TE&%}Gy+>v09>jzgWX#!-w8*51{dsJ-BKEhs+tAq zE=H5<@+OZKA?v*oJs=M*XF^8r^!@C29=-WSlJSRioSe2NERO$aAq~BfU1u|kJxvi6 ze5R%s?!qaub(plTT&?qd>GYU;F@Cp@aPokGx84yW3cosOD=0TD#;P;H0u&ROtETllN$qQM%%L z><^8O#L5lKyhmKn1XpVSR|~B9{`Rz%aqQ8WqE#1OScd5p85Z=DWt~3#d}!0QH3*c3 zcY`EFz!S4CaP_<~_{T3j&s%?28;nqDvP}%KRTm$i+!+T1)^6+H|2> zY*of?LA{LI>)~3lH z@AqDn?;!Bx+7&vwDR-oo-Us5-$vf)rBvch8_IQQEub}EL=Mwp&M{@ zN0T1)(psOzexokWDqW`6l6JH;kB*HNjx4#Vn|B-?ryYVjy6ENbnX9THR0Wp5>2(om zNiDje(hpZXO0TvxD*-t?dLQY+nr#IlZQ($Z)y%MB`>1hGq^p{6Je5jKm4%j=J>)J! zU0$Ma3X@UUA?%~gaVeRQnQDA#aC1%3Uc#g4J;I8v3XqgE3W>mXn(N@ClQ3;$fbsDX zF}rZvtx0}>#|_ogQi`p;xQxx!Lw+KJ=tz)dcP!q4eLajq-qfg%M8xW%%tyBU33y;< z!+Tw-i-q4s`V1dPC5|6GK2FCOJVoO)f}(T5x}DbB@fM|+^JTrhtIn4dn&O?F05SN} z84)EQx*Zj-aqL^fkhZVc%OC`#I&*_h;KBP`_9UWSFM37fY--5yX}^_Rnw2v?X{S<_ zlYMzj=!2n8UyQd|R(F6*5gqtEH35qZ+=GV@WosjiJ9bEJys&b;7?>Q*m9tk*N5!07 z-&h-Fe4V-FxSdTzzcxs3O5mt1y}G2-RIC1QdaQwZ1oZB#$`h58<*SWv-`ns*D0}I> z$6wU77%5AMeLCDXTQCDr2V$zBWWnCmwn)&qbq~g#k&8M0m&j_goiK&P|;IC)|?`eai*5biB z1xc9+NP%0DGOLEbZcCX7DPqBPnF*<)gur!$R8K?yzy5PI7e%~$?tH?ks { + CameraContent( + viewModel = viewModel, + onOpenSettings = { showSettings = true } + ) + } + cameraPermissionState.status.shouldShowRationale -> { + PermissionRationaleContent( + message = "URLFinder needs access to your camera to scan URLs and QR codes.", + onRequestPermission = { cameraPermissionState.launchPermissionRequest() } + ) + } + else -> { + PermissionRationaleContent( + message = "Camera permission is required to scan URLs and QR codes. Please grant it.", + onRequestPermission = { cameraPermissionState.launchPermissionRequest() } + ) + } + } +} + +/** + * Full-screen camera UI with live [PreviewView], flash toggle, settings button + * and the URL results overlay panel. + */ +@Composable +private fun CameraContent( + viewModel: CameraViewModel, + onOpenSettings: () -> Unit +) { + val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + val detectedUrls by viewModel.detectedUrls.collectAsState() + val isFlashOn by viewModel.isFlashOn.collectAsState() + var urlToOpen by remember { mutableStateOf(null) } + val uriHandler = androidx.compose.ui.platform.LocalUriHandler.current + + val previewView = remember { PreviewView(context) } + + // Start (or restart) the camera whenever the lifecycle resumes. + // This handles the return from Settings without crashing. + DisposableEffect(lifecycleOwner) { + val observer = LifecycleEventObserver { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + viewModel.startCamera(context, lifecycleOwner, previewView) + } + } + lifecycleOwner.lifecycle.addObserver(observer) + onDispose { lifecycleOwner.lifecycle.removeObserver(observer) } + } + + // Safety warning modal + urlToOpen?.let { url -> + SafetyWarningDialog( + url = url, + onConfirm = { + runCatching { uriHandler.openUri(url) } + urlToOpen = null + }, + onDismiss = { urlToOpen = null } + ) + } + + Box(modifier = Modifier.fillMaxSize()) { + // --- Camera preview layer --- + AndroidView( + factory = { previewView }, + modifier = Modifier.fillMaxSize() + ) + + // --- Scanning overlay --- + ScanningOverlay() + + // --- Top action bar (flash + settings) β€” respects status bar height --- + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.TopEnd) + .statusBarsPadding() + .padding(horizontal = 12.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.End + ) { + // Flash toggle button + IconButton( + onClick = { viewModel.toggleFlash() }, + modifier = Modifier + .background( + color = if (isFlashOn) Color(0xFFFFD600) else Color.Black.copy(alpha = 0.55f), + shape = MaterialTheme.shapes.small + ) + ) { + Icon( + painter = painterResource( + id = if (isFlashOn) R.drawable.ic_flash_on else R.drawable.ic_flash_off + ), + contentDescription = if (isFlashOn) "Flash on" else "Flash off", + tint = if (isFlashOn) Color.Black else Color.White + ) + } + + Spacer(modifier = Modifier.width(8.dp)) + + // Settings button + IconButton( + onClick = onOpenSettings, + modifier = Modifier + .background( + color = Color.Black.copy(alpha = 0.55f), + shape = MaterialTheme.shapes.small + ) + ) { + Icon( + imageVector = Icons.Default.Settings, + contentDescription = "Settings", + tint = Color.White + ) + } + } + + // --- URL results panel anchored to the bottom --- + AnimatedVisibility( + visible = detectedUrls.isNotEmpty(), + modifier = Modifier.align(Alignment.BottomCenter), + enter = slideInVertically { it } + fadeIn(), + exit = fadeOut() + ) { + Surface( + color = MaterialTheme.colorScheme.surface.copy(alpha = 0.93f), + tonalElevation = 8.dp, + shadowElevation = 8.dp, + shape = MaterialTheme.shapes.large + ) { + Column(modifier = Modifier.padding(top = 8.dp)) { + // Header + Text( + text = "Detected URLs (${detectedUrls.size})", + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp) + ) + + // URL list β€” items open the safety warning dialog + UrlResultsPanel( + urls = detectedUrls, + onUrlClick = { urlToOpen = it.url } + ) + + Spacer(modifier = Modifier.height(4.dp)) + + // Clear button β€” full width at the bottom of the panel + Button( + onClick = { viewModel.clearResults() }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error + ) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_link), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + Spacer(modifier = Modifier.width(6.dp)) + Text("Clear results") + } + } + } + } + } +} + +/** + * Semi-transparent scanning overlay with corner guides and a hint label. + */ +@Composable +private fun ScanningOverlay() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Icon( + painter = painterResource(id = R.drawable.ic_scan_frame), + contentDescription = "Scan area", + tint = Color.White.copy(alpha = 0.8f), + modifier = Modifier.size(240.dp) + ) + Text( + text = "Point the camera at a URL or QR code", + color = Color.White, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + modifier = Modifier + .padding(horizontal = 24.dp, vertical = 8.dp) + .background( + Color.Black.copy(alpha = 0.45f), + shape = MaterialTheme.shapes.small + ) + .padding(horizontal = 12.dp, vertical = 6.dp) + ) + } + } +} + +/** + * Displayed when camera permission has not been granted yet. + * + * @param message Human-readable explanation of why the permission is needed. + * @param onRequestPermission Lambda called when the user taps the grant button. + */ +@Composable +private fun PermissionRationaleContent(message: String, onRequestPermission: () -> Unit) { + Box( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background), + contentAlignment = Alignment.Center + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(32.dp) + ) { + // Logo shown in full color (no tint) + Icon( + painter = painterResource(id = R.drawable.ic_urlfinder_logo), + contentDescription = "URLFinder logo", + tint = Color.Unspecified, + modifier = Modifier.size(96.dp) + ) + Text( + text = "URLFinder", + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(top = 16.dp, bottom = 8.dp) + ) + Text( + text = message, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 24.dp) + ) + Button(onClick = onRequestPermission) { + Text("Grant Camera Permission") + } + } + } +} diff --git a/app/src/main/java/com/manalejandro/urlfinder/CameraViewModel.kt b/app/src/main/java/com/manalejandro/urlfinder/CameraViewModel.kt new file mode 100644 index 0000000..d726ec1 --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/CameraViewModel.kt @@ -0,0 +1,237 @@ +package com.manalejandro.urlfinder + +import android.content.Context +import android.util.Log +import android.util.Patterns +import androidx.annotation.OptIn +import androidx.camera.core.Camera +import androidx.camera.core.CameraSelector +import androidx.camera.core.ExperimentalGetImage +import androidx.camera.core.ImageAnalysis +import androidx.camera.core.ImageProxy +import androidx.camera.core.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.view.PreviewView +import androidx.core.content.ContextCompat +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.barcode.common.Barcode +import com.google.mlkit.vision.common.InputImage +import com.google.mlkit.vision.text.TextRecognition +import com.google.mlkit.vision.text.latin.TextRecognizerOptions +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import java.util.concurrent.Executors +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicLong + +/** Source type that originated the detected URL */ +enum class UrlSource { TEXT, QR_CODE } + +/** A URL found by the scanner with its source type */ +data class DetectedUrl( + val url: String, + val source: UrlSource +) + +/** + * ViewModel responsible for managing the camera lifecycle and URL detection pipeline. + * Uses CameraX for camera access, ML Kit Text Recognition for detecting URLs in + * plain text, and ML Kit Barcode Scanning for QR codes. + */ +class CameraViewModel : ViewModel() { + + companion object { + private const val TAG = "CameraViewModel" + /** Minimum interval between frame analyses in milliseconds (throttle) */ + private const val ANALYSIS_INTERVAL_MS = 800L + } + + private val _detectedUrls = MutableStateFlow>(emptyList()) + /** Live stream of all URLs detected in the current camera session */ + val detectedUrls: StateFlow> = _detectedUrls.asStateFlow() + + private val _isScanning = MutableStateFlow(false) + /** Whether the camera analyzer is actively processing frames */ + val isScanning: StateFlow = _isScanning.asStateFlow() + + private val _isFlashOn = MutableStateFlow(false) + /** Whether the camera torch/flash is currently enabled */ + val isFlashOn: StateFlow = _isFlashOn.asStateFlow() + + /** Exposed repository β€” injected from outside (e.g. from Application context) */ + var historyRepository: UrlHistoryRepository? = null + + private val analysisExecutor = Executors.newSingleThreadExecutor() + private val textRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) + private val barcodeScanner = BarcodeScanning.getClient() + private val lastAnalysisTimestamp = AtomicLong(0L) + private val isProcessing = AtomicBoolean(false) + private var camera: Camera? = null + + /** URL regex backed by Android's built-in Patterns.WEB_URL */ + private val urlRegex = Patterns.WEB_URL.toRegex() + + /** + * Binds CameraX use cases (Preview + ImageAnalysis) to the given [lifecycleOwner]. + * + * @param context Application or Activity context used to get the camera provider. + * @param lifecycleOwner The lifecycle owner that controls camera lifetime. + * @param previewView The [PreviewView] that will render the camera feed. + */ + fun startCamera( + context: Context, + lifecycleOwner: LifecycleOwner, + previewView: PreviewView + ) { + val cameraProviderFuture = ProcessCameraProvider.getInstance(context) + cameraProviderFuture.addListener({ + val cameraProvider = cameraProviderFuture.get() + + val preview = Preview.Builder().build().also { + it.surfaceProvider = previewView.surfaceProvider + } + + val imageAnalysis = ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build() + .also { analysis -> + analysis.setAnalyzer(analysisExecutor) { imageProxy -> + analyzeFrame(imageProxy) + } + } + + try { + cameraProvider.unbindAll() + camera = cameraProvider.bindToLifecycle( + lifecycleOwner, + CameraSelector.DEFAULT_BACK_CAMERA, + preview, + imageAnalysis + ) + // Restore flash state if it was on before rebind + camera?.cameraControl?.enableTorch(_isFlashOn.value) + _isScanning.value = true + } catch (e: Exception) { + Log.e(TAG, "Camera binding failed", e) + } + }, ContextCompat.getMainExecutor(context)) + } + + /** + * Toggles the camera torch on or off. + */ + fun toggleFlash() { + val newState = !_isFlashOn.value + _isFlashOn.value = newState + camera?.cameraControl?.enableTorch(newState) + } + + /** + * Analyzes a single camera [frame][ImageProxy] for URLs (text) and QR codes. + * Throttles analysis to [ANALYSIS_INTERVAL_MS] ms to reduce CPU usage. + */ + @OptIn(ExperimentalGetImage::class) + private fun analyzeFrame(imageProxy: ImageProxy) { + val now = System.currentTimeMillis() + val elapsed = now - lastAnalysisTimestamp.get() + + // Throttle: skip frames that arrive too quickly + if (elapsed < ANALYSIS_INTERVAL_MS || !isProcessing.compareAndSet(false, true)) { + imageProxy.close() + return + } + lastAnalysisTimestamp.set(now) + + val mediaImage = imageProxy.image + if (mediaImage == null) { + imageProxy.close() + isProcessing.set(false) + return + } + + val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) + val foundUrls = mutableListOf() + var pendingTasks = 2 + + fun checkDone() { + pendingTasks-- + if (pendingTasks == 0) { + mergeResults(foundUrls) + imageProxy.close() + isProcessing.set(false) + } + } + + // --- Text recognition (URLs in plain text) --- + textRecognizer.process(inputImage) + .addOnSuccessListener { visionText -> + val urls = urlRegex.findAll(visionText.text) + .map { it.value.normalizeUrl() } + .filter { it.isNotBlank() } + .map { DetectedUrl(it, UrlSource.TEXT) } + .toList() + synchronized(foundUrls) { foundUrls.addAll(urls) } + } + .addOnFailureListener { e -> Log.e(TAG, "Text recognition failed", e) } + .addOnCompleteListener { checkDone() } + + // --- Barcode / QR code scanning --- + barcodeScanner.process(inputImage) + .addOnSuccessListener { barcodes -> + val urls = barcodes + .filter { it.valueType == Barcode.TYPE_URL || it.format == Barcode.FORMAT_QR_CODE } + .mapNotNull { it.url?.url ?: it.rawValue } + .filter { it.looksLikeUrl() } + .map { DetectedUrl(it.normalizeUrl(), UrlSource.QR_CODE) } + synchronized(foundUrls) { foundUrls.addAll(urls) } + } + .addOnFailureListener { e -> Log.e(TAG, "Barcode scanning failed", e) } + .addOnCompleteListener { checkDone() } + } + + /** + * Merges newly detected URLs with the existing accumulated list, + * avoiding exact-URL duplicates. Also saves to history. + */ + private fun mergeResults(newUrls: List) { + viewModelScope.launch { + if (newUrls.isEmpty()) return@launch + val existing = _detectedUrls.value.map { it.url }.toSet() + val unique = newUrls.filter { it.url !in existing } + if (unique.isNotEmpty()) { + _detectedUrls.value = _detectedUrls.value + unique + unique.forEach { historyRepository?.add(it) } + } + } + } + + /** Clears the accumulated URL list so the user can start a fresh scan */ + fun clearResults() { + _detectedUrls.value = emptyList() + } + + override fun onCleared() { + super.onCleared() + analysisExecutor.shutdown() + textRecognizer.close() + barcodeScanner.close() + } +} + +// --- Extension helpers --- + +/** Ensures a URL string starts with a proper HTTP/HTTPS scheme */ +private fun String.normalizeUrl(): String = + if (startsWith("http://") || startsWith("https://")) this + else "https://$this" + +/** Returns true if the string looks like a URL */ +private fun String.looksLikeUrl(): Boolean = + Patterns.WEB_URL.matcher(this).matches() || + startsWith("http://") || + startsWith("https://") diff --git a/app/src/main/java/com/manalejandro/urlfinder/MainActivity.kt b/app/src/main/java/com/manalejandro/urlfinder/MainActivity.kt new file mode 100644 index 0000000..410b82a --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/MainActivity.kt @@ -0,0 +1,32 @@ +package com.manalejandro.urlfinder + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.manalejandro.urlfinder.ui.theme.URLFinderTheme + +/** + * Single-activity entry point for URLFinder. + * Creates the [UrlHistoryRepository] and hosts [CameraScreen]. + */ +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + URLFinderTheme { + Surface(modifier = Modifier.fillMaxSize()) { + val context = LocalContext.current + val repository = remember { UrlHistoryRepository(context) } + CameraScreen(repository = repository) + } + } + } + } +} diff --git a/app/src/main/java/com/manalejandro/urlfinder/SettingsScreen.kt b/app/src/main/java/com/manalejandro/urlfinder/SettingsScreen.kt new file mode 100644 index 0000000..f6e165a --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/SettingsScreen.kt @@ -0,0 +1,451 @@ +package com.manalejandro.urlfinder + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * Settings screen with two tabs: URL History and About. + * + * @param repository History repository to read/clear entries. + * @param onBack Callback invoked when the user taps the back button. + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingsScreen( + repository: UrlHistoryRepository, + onBack: () -> Unit +) { + var selectedTab by remember { mutableIntStateOf(0) } + val tabs = listOf("History", "About") + + Scaffold( + topBar = { + TopAppBar( + title = { Text("Settings") }, + navigationIcon = { + IconButton(onClick = onBack) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = "Back" + ) + } + } + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + TabRow(selectedTabIndex = selectedTab) { + tabs.forEachIndexed { index, title -> + Tab( + selected = selectedTab == index, + onClick = { selectedTab = index }, + text = { Text(title) } + ) + } + } + + when (selectedTab) { + 0 -> HistoryTab(repository = repository) + 1 -> AboutTab() + } + } + } +} + +// --------------------------------------------------------------------------- +// History Tab +// --------------------------------------------------------------------------- + +@Composable +private fun HistoryTab(repository: UrlHistoryRepository) { + val history by repository.history.collectAsState() + var urlToOpen by remember { mutableStateOf(null) } + var showClearConfirm by remember { mutableStateOf(false) } + val uriHandler = LocalUriHandler.current + + // Dangerous-URL warning dialog + urlToOpen?.let { url -> + SafetyWarningDialog( + url = url, + onConfirm = { + runCatching { uriHandler.openUri(url) } + urlToOpen = null + }, + onDismiss = { urlToOpen = null } + ) + } + + // Clear all confirmation dialog + if (showClearConfirm) { + AlertDialog( + onDismissRequest = { showClearConfirm = false }, + title = { Text("Clear history") }, + text = { Text("Are you sure you want to delete all saved URLs? This cannot be undone.") }, + confirmButton = { + Button( + onClick = { + repository.clear() + showClearConfirm = false + }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error + ) + ) { Text("Delete all") } + }, + dismissButton = { + TextButton(onClick = { showClearConfirm = false }) { Text("Cancel") } + } + ) + } + + if (history.isEmpty()) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Icon( + painter = painterResource(id = R.drawable.ic_link), + contentDescription = null, + tint = MaterialTheme.colorScheme.outlineVariant, + modifier = Modifier.size(64.dp) + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "No history yet", + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.outline + ) + Text( + text = "Scanned URLs will appear here", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.outlineVariant + ) + } + } + } else { + Column(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) { + items(history, key = { it.id }) { entry -> + HistoryItem( + entry = entry, + onClick = { urlToOpen = entry.url } + ) + HorizontalDivider( + modifier = Modifier.padding(horizontal = 16.dp), + color = MaterialTheme.colorScheme.outlineVariant + ) + } + } + + // Clear all button β€” full width at the bottom + Button( + onClick = { showClearConfirm = true }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error + ) + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.size(8.dp)) + Text("Clear all history") + } + } + } +} + +@Composable +private fun HistoryItem(entry: HistoryEntry, onClick: () -> Unit) { + val dateFormat = remember { SimpleDateFormat("MMM d, yyyy Β· HH:mm", Locale.getDefault()) } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 10.dp) + ) { + Icon( + painter = painterResource( + id = if (entry.source == UrlSource.QR_CODE) R.drawable.ic_qr_code else R.drawable.ic_link + ), + contentDescription = null, + tint = if (entry.source == UrlSource.QR_CODE) + MaterialTheme.colorScheme.secondary + else + MaterialTheme.colorScheme.primary, + modifier = Modifier.size(20.dp) + ) + Column( + modifier = Modifier + .weight(1f) + .padding(horizontal = 12.dp) + ) { + Text( + text = entry.url, + style = MaterialTheme.typography.bodyMedium.copy( + textDecoration = TextDecoration.Underline + ), + color = MaterialTheme.colorScheme.primary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = dateFormat.format(Date(entry.timestamp)), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.outline + ) + } + Icon( + painter = painterResource(id = R.drawable.ic_open_in_browser), + contentDescription = "Open in browser", + tint = MaterialTheme.colorScheme.outline, + modifier = Modifier.size(16.dp) + ) + } +} + +// --------------------------------------------------------------------------- +// About Tab +// --------------------------------------------------------------------------- + +@Composable +private fun AboutTab() { + val uriHandler = LocalUriHandler.current + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + item { + Spacer(modifier = Modifier.height(8.dp)) + // Multicolor logo (not tinted) + Icon( + painter = painterResource(id = R.drawable.ic_urlfinder_logo), + contentDescription = "URLFinder logo", + tint = androidx.compose.ui.graphics.Color.Unspecified, + modifier = Modifier.size(96.dp) + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "URLFinder", + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold + ) + Text( + text = "Version 1.0", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.outline + ) + } + + item { + HorizontalDivider() + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "URLFinder is a free and open-source Android app that uses your " + + "device camera to detect URLs in text and QR codes in real time, " + + "letting you open them directly in your browser.", + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.fillMaxWidth() + ) + } + + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.primaryContainer + ), + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + painter = painterResource(id = R.drawable.ic_open_source), + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(20.dp) + ) + Spacer(modifier = Modifier.size(8.dp)) + Text( + text = "Free & Open Source Software", + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onPrimaryContainer + ) + } + Text( + text = "URLFinder is released under the MIT License. " + + "You are free to use, modify and distribute it.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onPrimaryContainer + ) + } + } + } + + item { + OutlinedButton( + onClick = { + runCatching { + uriHandler.openUri("https://github.com/manalejandro/URLFinder") + } + }, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + painter = painterResource(id = R.drawable.ic_github), + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.size(8.dp)) + Text("View on GitHub") + } + } + + item { + HorizontalDivider() + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "Built with ❀️ using Kotlin, Jetpack Compose, CameraX & ML Kit", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.outline + ) + } + } +} + +// --------------------------------------------------------------------------- +// Safety Warning Dialog +// --------------------------------------------------------------------------- + +/** + * Modal dialog warning the user that the URL may be dangerous before opening it. + * + * @param url The URL that is about to be opened. + * @param onConfirm Called when the user accepts the risk and wants to proceed. + * @param onDismiss Called when the user cancels. + */ +@Composable +fun SafetyWarningDialog( + url: String, + onConfirm: () -> Unit, + onDismiss: () -> Unit +) { + AlertDialog( + onDismissRequest = onDismiss, + icon = { + Icon( + painter = painterResource(id = R.drawable.ic_warning), + contentDescription = null, + tint = MaterialTheme.colorScheme.error, + modifier = Modifier.size(32.dp) + ) + }, + title = { Text("Open URL?") }, + text = { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Text( + text = "⚠️ This URL may be dangerous. You are responsible for any " + + "content you access through it.", + style = MaterialTheme.typography.bodyMedium + ) + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.errorContainer + ) + ) { + Text( + text = url, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onErrorContainer, + maxLines = 3, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(8.dp) + ) + } + } + }, + confirmButton = { + Button( + onClick = onConfirm, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error + ) + ) { Text("Open anyway") } + }, + dismissButton = { + TextButton(onClick = onDismiss) { Text("Cancel") } + } + ) +} + diff --git a/app/src/main/java/com/manalejandro/urlfinder/UrlHistoryRepository.kt b/app/src/main/java/com/manalejandro/urlfinder/UrlHistoryRepository.kt new file mode 100644 index 0000000..51c049c --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/UrlHistoryRepository.kt @@ -0,0 +1,91 @@ +package com.manalejandro.urlfinder + +import android.content.Context +import androidx.core.content.edit +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import org.json.JSONArray +import org.json.JSONObject +import java.util.UUID + +/** + * A persisted URL history entry with a stable unique [id], timestamp and source type. + */ +data class HistoryEntry( + val id: String = UUID.randomUUID().toString(), + val url: String, + val source: UrlSource, + val timestamp: Long = System.currentTimeMillis() +) + +/** + * Repository that persists detected URLs locally using SharedPreferences (JSON). + * Provides a [StateFlow] of [HistoryEntry] items and operations to add/clear them. + */ +class UrlHistoryRepository(context: Context) { + + companion object { + private const val PREFS_NAME = "url_history_prefs" + private const val KEY_HISTORY = "history" + private const val MAX_ENTRIES = 200 + } + + private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + private val _history = MutableStateFlow>(load()) + /** Live list of persisted URL history entries, newest first. */ + val history: StateFlow> = _history.asStateFlow() + + /** + * Adds a [DetectedUrl] to history if it is not already present. + * Keeps at most [MAX_ENTRIES] entries. + */ + fun add(detectedUrl: DetectedUrl) { + val current = _history.value + if (current.any { it.url == detectedUrl.url }) return + val entry = HistoryEntry(url = detectedUrl.url, source = detectedUrl.source) + val updated = (listOf(entry) + current).take(MAX_ENTRIES) + _history.value = updated + save(updated) + } + + /** Removes all history entries from memory and disk. */ + fun clear() { + _history.value = emptyList() + prefs.edit { remove(KEY_HISTORY) } + } + + // --- Serialization --- + + private fun save(entries: List) { + val array = JSONArray() + entries.forEach { e -> + val obj = JSONObject().apply { + put("id", e.id) + put("url", e.url) + put("source", e.source.name) + put("ts", e.timestamp) + } + array.put(obj) + } + prefs.edit { putString(KEY_HISTORY, array.toString()) } + } + + private fun load(): List { + val json = prefs.getString(KEY_HISTORY, null) ?: return emptyList() + return runCatching { + val array = JSONArray(json) + (0 until array.length()).map { i -> + val obj = array.getJSONObject(i) + HistoryEntry( + id = obj.optString("id", UUID.randomUUID().toString()), + url = obj.getString("url"), + source = UrlSource.valueOf(obj.getString("source")), + timestamp = obj.getLong("ts") + ) + } + }.getOrDefault(emptyList()) + } +} + diff --git a/app/src/main/java/com/manalejandro/urlfinder/UrlResultsPanel.kt b/app/src/main/java/com/manalejandro/urlfinder/UrlResultsPanel.kt new file mode 100644 index 0000000..51df65a --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/UrlResultsPanel.kt @@ -0,0 +1,130 @@ +package com.manalejandro.urlfinder + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp + +/** + * Displays a scrollable list of [DetectedUrl] items. + * Each item triggers [onUrlClick] when tapped instead of opening the browser + * directly, allowing the caller to show a safety warning first. + * + * @param urls The list of detected URLs to display. + * @param onUrlClick Called with the tapped [DetectedUrl]. + */ +@Composable +fun UrlResultsPanel( + urls: List, + onUrlClick: (DetectedUrl) -> Unit = {} +) { + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 300.dp) + ) { + itemsIndexed(urls) { index, detectedUrl -> + UrlItem(detectedUrl = detectedUrl, onClick = { onUrlClick(detectedUrl) }) + if (index < urls.lastIndex) { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 16.dp), + color = MaterialTheme.colorScheme.outlineVariant + ) + } + } + } +} + +/** + * A single URL card item. + * Calls [onClick] when tapped so the parent can handle navigation/warnings. + * + * @param detectedUrl The URL data to display. + * @param onClick Callback invoked on tap. + */ +@Composable +private fun UrlItem(detectedUrl: DetectedUrl, onClick: () -> Unit) { + Card( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp) + ) { + // Icon varies by source type + Icon( + painter = painterResource( + id = if (detectedUrl.source == UrlSource.QR_CODE) + R.drawable.ic_qr_code + else + R.drawable.ic_link + ), + contentDescription = if (detectedUrl.source == UrlSource.QR_CODE) + "QR Code URL" + else + "Text URL", + tint = if (detectedUrl.source == UrlSource.QR_CODE) + MaterialTheme.colorScheme.secondary + else + MaterialTheme.colorScheme.primary, + modifier = Modifier.size(24.dp) + ) + + Spacer(modifier = Modifier.width(12.dp)) + + Column(modifier = Modifier.weight(1f)) { + Text( + text = if (detectedUrl.source == UrlSource.QR_CODE) "QR Code" else "Text", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.outline, + fontWeight = FontWeight.Medium + ) + Text( + text = detectedUrl.url, + style = MaterialTheme.typography.bodyMedium.copy( + textDecoration = TextDecoration.Underline + ), + color = MaterialTheme.colorScheme.primary, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + + Spacer(modifier = Modifier.width(8.dp)) + + Icon( + painter = painterResource(id = R.drawable.ic_open_in_browser), + contentDescription = "Open in browser", + tint = MaterialTheme.colorScheme.outline, + modifier = Modifier.size(18.dp) + ) + } + } +} diff --git a/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Color.kt b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Color.kt new file mode 100644 index 0000000..cf1f376 --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.manalejandro.urlfinder.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Theme.kt b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Theme.kt new file mode 100644 index 0000000..3759d7f --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.manalejandro.urlfinder.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun URLFinderTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Type.kt b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Type.kt new file mode 100644 index 0000000..ed5ed48 --- /dev/null +++ b/app/src/main/java/com/manalejandro/urlfinder/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.manalejandro.urlfinder.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_flash_off.xml b/app/src/main/res/drawable/ic_flash_off.xml new file mode 100644 index 0000000..2a01f8d --- /dev/null +++ b/app/src/main/res/drawable/ic_flash_off.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_flash_on.xml b/app/src/main/res/drawable/ic_flash_on.xml new file mode 100644 index 0000000..9d3348d --- /dev/null +++ b/app/src/main/res/drawable/ic_flash_on.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml new file mode 100644 index 0000000..2bfe162 --- /dev/null +++ b/app/src/main/res/drawable/ic_github.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..8c561c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_link.xml b/app/src/main/res/drawable/ic_link.xml new file mode 100644 index 0000000..ec08a83 --- /dev/null +++ b/app/src/main/res/drawable/ic_link.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_open_in_browser.xml b/app/src/main/res/drawable/ic_open_in_browser.xml new file mode 100644 index 0000000..b4cc0b9 --- /dev/null +++ b/app/src/main/res/drawable/ic_open_in_browser.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_open_source.xml b/app/src/main/res/drawable/ic_open_source.xml new file mode 100644 index 0000000..b7e671f --- /dev/null +++ b/app/src/main/res/drawable/ic_open_source.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_qr_code.xml b/app/src/main/res/drawable/ic_qr_code.xml new file mode 100644 index 0000000..c2c0d58 --- /dev/null +++ b/app/src/main/res/drawable/ic_qr_code.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_scan_frame.xml b/app/src/main/res/drawable/ic_scan_frame.xml new file mode 100644 index 0000000..cd85f9a --- /dev/null +++ b/app/src/main/res/drawable/ic_scan_frame.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_urlfinder_logo.xml b/app/src/main/res/drawable/ic_urlfinder_logo.xml new file mode 100644 index 0000000..239e011 --- /dev/null +++ b/app/src/main/res/drawable/ic_urlfinder_logo.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_warning.xml b/app/src/main/res/drawable/ic_warning.xml new file mode 100644 index 0000000..3fef0d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_warning.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..40ccaa2dc5a348af1c44829dce8c3852a6187492 GIT binary patch literal 2674 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..ec011ea0ae84a7b9736a8b125b79188b483b97ee GIT binary patch literal 2944 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 GpGkrB21ddF literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..2a8f05a2eb25b1f5aa3dbc6e304d35b744d7c225 GIT binary patch literal 10268 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..7dcdec880d1efda5041efd5669e800e9f90352a8 GIT binary patch literal 7618 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..31b2600 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #145CB7 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..acecebb --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,9 @@ + + URLFinder + URLFinder needs camera access to scan URLs and QR codes. + Grant Camera Permission + Detected URLs + Point the camera at a URL or QR code + Clear results + Open in browser + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..2c4d763 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +