├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── Share2ArchiveToday ├── .gitignore ├── app │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── data.minify.json │ │ ├── ic_launcher-playstore.png │ │ ├── java │ │ └── org │ │ │ └── gnosco │ │ │ └── share2archivetoday │ │ │ ├── ClearUrlsRulesManager.kt │ │ │ ├── Legacy.kt │ │ │ ├── MainActivity.kt │ │ │ └── WebURLMatcher.kt │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_adaptive_back.png │ │ ├── ic_launcher_adaptive_fore.png │ │ ├── ic_launcher_foreground.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_adaptive_back.png │ │ ├── ic_launcher_adaptive_fore.png │ │ ├── ic_launcher_foreground.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_adaptive_back.png │ │ ├── ic_launcher_adaptive_fore.png │ │ ├── ic_launcher_foreground.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_adaptive_back.png │ │ ├── ic_launcher_adaptive_fore.png │ │ ├── ic_launcher_foreground.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_adaptive_back.png │ │ ├── ic_launcher_adaptive_fore.png │ │ ├── ic_launcher_foreground.webp │ │ └── ic_launcher_round.webp │ │ ├── play_store_512.png │ │ ├── values-af │ │ └── strings.xml │ │ ├── values-am │ │ └── strings.xml │ │ ├── values-ar │ │ └── strings.xml │ │ ├── values-az-rAZ │ │ └── strings.xml │ │ ├── values-be │ │ └── strings.xml │ │ ├── values-bg │ │ └── strings.xml │ │ ├── values-bn-rBD │ │ └── strings.xml │ │ ├── values-ca │ │ └── strings.xml │ │ ├── values-cs-rCZ │ │ └── strings.xml │ │ ├── values-da-rDK │ │ └── strings.xml │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-el-rGR │ │ └── strings.xml │ │ ├── values-et │ │ └── strings.xml │ │ ├── values-eu-rES │ │ └── strings.xml │ │ ├── values-fi-rFI │ │ └── strings.xml │ │ ├── values-fil │ │ └── strings.xml │ │ ├── values-fr-rCA │ │ └── strings.xml │ │ ├── values-fr-rFR │ │ └── strings.xml │ │ ├── values-gl-rES │ │ └── strings.xml │ │ ├── values-gu │ │ └── strings.xml │ │ ├── values-hi │ │ └── strings.xml │ │ ├── values-hr │ │ └── strings.xml │ │ ├── values-hy-rAM │ │ └── strings.xml │ │ ├── values-iw │ │ └── strings.xml │ │ ├── values-ka │ │ └── strings.xml │ │ ├── values-my-rMM │ │ └── strings.xml │ │ ├── values-nl-rNL │ │ └── strings.xml │ │ ├── values-sq │ │ └── strings.xml │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ ├── values-zh-rHK │ │ └── strings.xml │ │ ├── values-zh-rTW │ │ └── strings.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml ├── build.gradle.kts ├── gradle.properties ├── gradle │ ├── libs.versions.toml │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts ├── fastlane └── metadata │ └── android │ ├── ar │ ├── full_description.txt │ ├── short_description.txt │ └── title.txt │ └── en-US │ ├── full_description.txt │ ├── images │ ├── icon.png │ └── phoneScreenshots │ │ ├── 0.png │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ ├── short_description.txt │ └── title.txt ├── ios └── Share-2-Archive-Today │ ├── Share-2-Archive-Today.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ ├── Share-2-Archive-Today.xcscheme │ │ │ └── URLShareExtension.xcscheme │ └── xcuserdata │ │ └── gabirelfair.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── Share-2-Archive-Today │ ├── AppDelegate.swift │ ├── ArchiveURLService.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ └── icon.png │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── FAQController.swift │ ├── FloatingButton.swift │ ├── Info.plist │ ├── SceneDelegate.swift │ ├── Share-2-Archive-Today.entitlements │ ├── URLProcessor.swift │ ├── URLStore.swift │ ├── ViewController.swift │ └── WelcomeOverlayView.swift │ └── URLShareExtension │ ├── Base.lproj │ └── MainInterface.storyboard │ ├── Info.plist │ ├── PrivacyInfo.xcprivacy │ ├── QRCodeScanner.swift │ ├── ShareViewController.swift │ ├── Toast.swift │ ├── URLProcessingManager.swift │ └── URLShareExtension.entitlements └── privacy.policy /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle/ 3 | build/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Log/OS Files 9 | *.log 10 | 11 | # Android Studio generated files and folders 12 | captures/ 13 | .externalNativeBuild/ 14 | .cxx/ 15 | *.apk 16 | output.json 17 | 18 | # IntelliJ 19 | *.iml 20 | .idea/ 21 | misc.xml 22 | deploymentTargetDropDown.xml 23 | render.experimental.xml 24 | 25 | # Keystore files 26 | *.jks 27 | *.keystore 28 | 29 | # Google Services (e.g. APIs or Firebase) 30 | google-services.json 31 | 32 | # Android Profiling 33 | *.hprof 34 | .DS_Store 35 | 36 | 37 | *.iml 38 | .gradle 39 | /local.properties 40 | /.idea/caches 41 | /.idea/libraries 42 | /.idea/modules.xml 43 | /.idea/workspace.xml 44 | /.idea/navEditor.xml 45 | /.idea/assetWizardSettings.xml 46 | .DS_Store 47 | /build 48 | /captures 49 | .externalNativeBuild 50 | .cxx 51 | local.properties 52 | key2 53 | key3 54 | /Share2ArchiveToday/app/release 55 | *.kts 56 | *.dm 57 | *.der 58 | *.pem 59 | ios/Share-2-Archive-Today/Share-2-Archive-Today.xcodeproj/project.xcworkspace/xcuserdata/gabirelfair.xcuserdatad/UserInterfaceState.xcuserstate 60 | /ios/Share-2-Archive-Today/Share-2-Archive-Today.xcodeproj/project.xcworkspace 61 | /ios/Share-2-Archive-Today/Share-2-Archive-Today.xcodeproj/project.xcworkspace/xcuserdata 62 | ios/Share-2-Archive-Today/Share-2-Archive-Today.xcodeproj/project.xcworkspace/xcuserdata/gabirelfair.xcuserdatad/UserInterfaceState.xcuserstate 63 | ios/Share-2-Archive-Today/Share-2-Archive-Today.xcodeproj/project.xcworkspace/xcuserdata/gabirelfair.xcuserdatad/UserInterfaceState.xcuserstate 64 | Share2ArchiveToday/app/mapping.txt 65 | key9 66 | Share2ArchiveToday/app/seeds.txt 67 | Share2ArchiveToday/app/unused.txt 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Share 2 Archive Today 2 | [Download on Apple App Store](https://apps.apple.com/us/app/share-2-archive-today/id6742428176) 3 | [![Moonlight for ChromeOS](https://moonlight-stream.org/images/chrome_webstore.png)](https://chromewebstore.google.com/detail/archive-webpage/falfcajjjjfjjlfabnfaadepcoagegip) 4 | 5 | [Get it on Google Play](https://play.google.com/store/apps/details?id=org.gnosco.share2archivetoday) 6 | [Get it on F-Droid](https://f-droid.org/en/packages/org.gnosco.share2archivetoday/) 9 | [Get it on IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/org.gnosco.share2archivetoday?repo=main) 12 | 13 | 14 | 15 | 16 | 17 | Simple app to add an icon to your share menu to publically archive a URL on Archive.today and Archive.Is 18 | 19 | It does not spy on you or collect any data. Find it on the [Google Play Store](https://play.google.com/store/apps/details?id=org.gnosco.share2archivetoday). 20 | 21 | Find the companion chrome browser app on the [Chrome Web Store](https://chromewebstore.google.com/detail/archive-webpage/falfcajjjjfjjlfabnfaadepcoagegip). 22 | 23 | ## _Features_ 24 | - ⭐️ Finds the first link in any shared text, no need to select just the url 25 | - ⭐️ Protect your privacy by removing tracking tokens in URL 26 | - ⭐️ Substack email nag screens are now bypassed 27 | - ⭐️ Outlinks can be archived directly from archived pages 28 | - ⭐️ WesternJournal.com URLs can now be archived 29 | 30 | 31 | 32 | 33 | Also, in order for this app to be listed on the google play store, I have to reference the [privacy polcy](https://github.com/gabefair/Share-2-Archive-Today/blob/main/privacy.policy). 34 | -------------------------------------------------------------------------------- /Share2ArchiveToday/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /Share2ArchiveToday/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | alias(libs.plugins.jetbrains.kotlin.android) 4 | } 5 | 6 | android { 7 | namespace = "org.gnosco.share2archivetoday" 8 | compileSdk = 35 9 | 10 | defaultConfig { 11 | applicationId = "org.gnosco.share2archivetoday" 12 | minSdk = 3 13 | targetSdk = 34 14 | versionCode = 44 15 | versionName = "4.4" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | isMinifyEnabled = true 21 | isShrinkResources = true 22 | proguardFiles( 23 | getDefaultProguardFile("proguard-android-optimize.txt"), 24 | "proguard-rules.pro" 25 | ) 26 | } 27 | debug { 28 | isTestCoverageEnabled = true 29 | } 30 | } 31 | 32 | compileOptions { 33 | sourceCompatibility = JavaVersion.VERSION_1_8 34 | targetCompatibility = JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = "1.8" 39 | } 40 | 41 | packaging { 42 | resources { 43 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 44 | } 45 | } 46 | 47 | dependenciesInfo { // The name of these variables are misleading, they need to be false in order to make the app more transparent. 48 | includeInApk = false 49 | includeInBundle = false 50 | } 51 | } 52 | 53 | dependencies { 54 | implementation("com.google.zxing:core:3.5.3") 55 | } 56 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | ##---------------Begin: App Specific Rules ---------- 2 | -keep class org.gnosco.share2archivetoday.MainActivity {*;} 3 | -keep class androidx.compose.** { *; } 4 | 5 | ##---------------Begin: Stripping Logs ---------- 6 | # Strip all log calls 7 | -assumenosideeffects class android.util.Log { 8 | public static boolean isLoggable(java.lang.String, int); 9 | public static int v(...); 10 | public static int d(...); 11 | public static int i(...); 12 | public static int w(...); 13 | public static int e(...); 14 | public static int wtf(...); 15 | } 16 | 17 | ##---------------Begin: ZXing Library Rules ---------- 18 | # Keep only necessary ZXing classes 19 | -keep class com.google.zxing.BarcodeFormat { *; } 20 | -keep class com.google.zxing.DecodeHintType { *; } 21 | -keep class com.google.zxing.MultiFormatReader { *; } 22 | -keep class com.google.zxing.Result { *; } 23 | -keep class com.google.zxing.BinaryBitmap { *; } 24 | -keep class com.google.zxing.RGBLuminanceSource { *; } 25 | -keep class com.google.zxing.common.HybridBinarizer { *; } 26 | -keep class com.google.zxing.NotFoundException { *; } 27 | 28 | ##---------------Begin: General Optimization Rules ---------- 29 | # Remove all debugging info from all classes 30 | -optimizationpasses 5 31 | -dontusemixedcaseclassnames 32 | -dontskipnonpubliclibraryclasses 33 | -dontskipnonpubliclibraryclassmembers 34 | -dontpreverify 35 | -verbose 36 | -dump class_files.txt 37 | -printseeds seeds.txt 38 | -printusage unused.txt 39 | -printmapping mapping.txt 40 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 41 | 42 | # Preserve the special static methods that are required in all enumeration classes 43 | -keepclassmembers enum * { 44 | public static **[] values(); 45 | public static ** valueOf(java.lang.String); 46 | } 47 | 48 | # Keep necessary Android components 49 | -keep public class * extends android.app.Activity 50 | -keep public class * extends android.app.Application 51 | -keep public class * extends android.content.BroadcastReceiver 52 | -keep public class * extends android.content.ContentProvider 53 | 54 | # Keep legacy extension methods 55 | -keepclassmembers class org.gnosco.share2archivetoday.* { 56 | public static * legacy*(...); 57 | } 58 | 59 | # Keep the application's entry points 60 | -keepattributes *Annotation* 61 | 62 | # Remove unused code, resources, attributes in XMLs 63 | -keepattributes SourceFile,LineNumberTable -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/java/org/gnosco/share2archivetoday/Legacy.kt: -------------------------------------------------------------------------------- 1 | package org.gnosco.share2archivetoday 2 | 3 | import android.net.Uri 4 | import java.util.Collections 5 | 6 | fun Uri.legacyGetQueryParameterNames(): Set { 7 | if (isOpaque()) { 8 | throw UnsupportedOperationException("This isn't a hierarchical URI.") 9 | } 10 | 11 | val query: String = getEncodedQuery() 12 | ?: return emptySet() 13 | 14 | val names: MutableSet = LinkedHashSet() 15 | var start = 0 16 | do { 17 | val next = query.indexOf('&', start) 18 | val end = if ((next == -1)) query.length else next 19 | 20 | var separator = query.indexOf('=', start) 21 | if (separator > end || separator == -1) { 22 | separator = end 23 | } 24 | 25 | val name = query.substring(start, separator) 26 | names.add(Uri.decode(name)) 27 | 28 | // Move start to end of name. 29 | start = end + 1 30 | } while (start < query.length) 31 | 32 | return Collections.unmodifiableSet(names) 33 | } 34 | 35 | fun Uri.Builder.legacyClearQuery(): Uri.Builder { 36 | return query(null) 37 | } -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/java/org/gnosco/share2archivetoday/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package org.gnosco.share2archivetoday 2 | // This file is: MainActivity.kt 3 | 4 | import WebURLMatcher 5 | import android.app.Activity 6 | import android.content.Intent 7 | import android.net.Uri 8 | import android.os.Bundle 9 | import android.util.Log 10 | 11 | import android.graphics.Bitmap 12 | import android.graphics.BitmapFactory 13 | import com.google.zxing.* 14 | import com.google.zxing.common.HybridBinarizer 15 | import kotlin.math.max 16 | import android.widget.Toast 17 | 18 | open class MainActivity : Activity() { 19 | private lateinit var clearUrlsRulesManager: ClearUrlsRulesManager 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | 24 | // Initialize ClearURLs rules manager 25 | clearUrlsRulesManager = ClearUrlsRulesManager(applicationContext) 26 | 27 | handleShareIntent(intent) 28 | } 29 | 30 | override fun onNewIntent(intent: Intent?) { 31 | super.onNewIntent(intent) 32 | handleShareIntent(intent) 33 | } 34 | 35 | private fun handleShareIntent(intent: Intent?) { 36 | if (intent?.action == Intent.ACTION_SEND) { 37 | when (intent.type) { 38 | "text/plain" -> { 39 | intent.getStringExtra(Intent.EXTRA_TEXT)?.let { sharedText -> 40 | Log.d("MainActivity", "Shared text: $sharedText") 41 | val url = extractUrl(sharedText) 42 | 43 | if (url != null) { 44 | threeSteps(url) 45 | } else { 46 | Toast.makeText(this, "No URL found in shared text", Toast.LENGTH_SHORT).show() 47 | finish() 48 | } 49 | } 50 | } 51 | else -> { 52 | // Handle image shares 53 | if (intent.type?.startsWith("image/") == true) { 54 | try { 55 | val imageUri = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { 56 | intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java) 57 | } else { 58 | @Suppress("DEPRECATION") 59 | intent.getParcelableExtra(Intent.EXTRA_STREAM) 60 | } 61 | 62 | imageUri?.let { 63 | handleImageShare(it) 64 | } 65 | } catch (e: Exception) { 66 | Log.e("MainActivity", "Error handling image share", e) 67 | Toast.makeText(this, "Share 2 Archive did not like that image", Toast.LENGTH_SHORT).show() 68 | finish() 69 | } 70 | } 71 | } 72 | } 73 | } 74 | finish() 75 | } 76 | 77 | internal fun threeSteps(url: String) { 78 | val processedUrl = processArchiveUrl(url) 79 | val cleanedUrl = handleURL(processedUrl) 80 | openInBrowser("https://archive.today/?run=1&url=${Uri.encode(cleanedUrl)}") 81 | } 82 | 83 | internal fun handleImageShare(imageUri: Uri) { 84 | try { 85 | val qrUrl = extractUrl(extractQRCodeFromImage(imageUri)) 86 | if (qrUrl != null) { 87 | threeSteps(qrUrl) 88 | Toast.makeText(this, "URL found in QR code", Toast.LENGTH_SHORT).show() 89 | } else { 90 | Log.d("MainActivity", "No QR code found in image") 91 | Toast.makeText(this, "No URL found in QR code image", Toast.LENGTH_SHORT).show() 92 | finish() 93 | } 94 | } catch (e: Exception) { 95 | Log.e("MainActivity", "Error processing QR code", e) 96 | Toast.makeText(this, "Error processing QR code", Toast.LENGTH_SHORT).show() 97 | finish() 98 | } 99 | } 100 | 101 | /** 102 | * Main URL handling method that combines ClearURLs rules with platform-specific optimizations 103 | */ 104 | internal fun handleURL(url: String): String { 105 | // First clean with ClearURLs rules 106 | var rulesCleanedUrl = url 107 | if (clearUrlsRulesManager.areRulesLoaded()) { 108 | rulesCleanedUrl = clearUrlsRulesManager.clearUrl(url) 109 | } 110 | rulesCleanedUrl = cleanTrackingParamsFromUrl(rulesCleanedUrl) 111 | 112 | // Then apply additional platform-specific optimizations that might not be in the rules 113 | return applyPlatformSpecificOptimizations(rulesCleanedUrl) 114 | } 115 | 116 | /** 117 | * Apply platform-specific optimizations that may not be covered by ClearURLs rules 118 | */ 119 | internal fun applyPlatformSpecificOptimizations(url: String): String { 120 | val uri = Uri.parse(url) 121 | val newUriBuilder = uri.buildUpon() 122 | var changed = false 123 | 124 | // YouTube-specific handling 125 | if (uri.host?.contains("youtube.com") == true || uri.host?.contains("youtu.be") == true) { 126 | // Convert shorts to regular videos 127 | if (uri.path?.contains("/shorts/") == true) { 128 | newUriBuilder.path(uri.path?.replace("/shorts/", "/v/")) 129 | changed = true 130 | } 131 | 132 | // Remove music. prefix 133 | val modifiedHost = uri.host?.removePrefix("music.") 134 | if (modifiedHost != uri.host) { 135 | newUriBuilder.authority(modifiedHost) 136 | changed = true 137 | } 138 | 139 | // Handle nested query parameters in YouTube search links 140 | val nestedQueryParams = uri.getQueryParameter("q") 141 | if (nestedQueryParams != null && nestedQueryParams.contains("?")) { 142 | try { 143 | val nestedUri = Uri.parse(nestedQueryParams) 144 | val newNestedUriBuilder = nestedUri.buildUpon().legacyClearQuery() 145 | 146 | nestedUri.legacyGetQueryParameterNames().forEach { nestedParam -> 147 | if (!isTrackingParam(nestedParam)) { 148 | newNestedUriBuilder.appendQueryParameter(nestedParam, nestedUri.getQueryParameter(nestedParam)) 149 | } 150 | } 151 | 152 | newUriBuilder.appendQueryParameter("q", newNestedUriBuilder.build().toString()) 153 | changed = true 154 | } catch (e: Exception) { 155 | Log.e("MainActivity", "Error handling nested query params", e) 156 | } 157 | } 158 | } 159 | 160 | // Substack-specific handling 161 | else if(uri.host?.endsWith(".substack.com") == true) { 162 | // Add "no_cover=true" parameter for better archive quality 163 | if (uri.getQueryParameter("no_cover") == null) { 164 | newUriBuilder.appendQueryParameter("no_cover", "true") 165 | changed = true 166 | } 167 | } 168 | 169 | else if (uri.host?.equals("t.me", ignoreCase = true) == true) { 170 | val path = uri.path?.trimStart('/') ?: "" 171 | if (!path.startsWith("s/") && path.isNotEmpty()) { 172 | newUriBuilder.path("/s/$path") //This is to archive some parts of the group chat if the web preview feature is enabled, otherwise the about page will be shown by telegram. 173 | changed = true 174 | } 175 | } 176 | 177 | return if (changed) newUriBuilder.build().toString() else url 178 | } 179 | 180 | internal fun extractQRCodeFromImage(imageUri: Uri): String { 181 | val inputStream = contentResolver.openInputStream(imageUri) ?: return "" 182 | 183 | // Read image dimensions first 184 | val options = BitmapFactory.Options().apply { 185 | inJustDecodeBounds = true 186 | } 187 | BitmapFactory.decodeStream(inputStream, null, options) 188 | inputStream.close() 189 | 190 | // Calculate sample size to avoid OOM 191 | val maxDimension = max(options.outWidth, options.outHeight) 192 | val sampleSize = max(1, maxDimension / 2048) 193 | 194 | // Read the actual bitmap with sampling 195 | val scaledOptions = BitmapFactory.Options().apply { 196 | inSampleSize = sampleSize 197 | inPreferredConfig = Bitmap.Config.ARGB_8888 198 | } 199 | 200 | contentResolver.openInputStream(imageUri)?.use { stream -> 201 | val bitmap = BitmapFactory.decodeStream(stream, null, scaledOptions) ?: return "" 202 | 203 | try { 204 | // Convert to ZXing format 205 | val width = bitmap.width 206 | val height = bitmap.height 207 | val pixels = IntArray(width * height) 208 | bitmap.getPixels(pixels, 0, width, 0, 0, width, height) 209 | 210 | val source = RGBLuminanceSource(width, height, pixels) 211 | val binarizer = HybridBinarizer(source) 212 | val binaryBitmap = BinaryBitmap(binarizer) 213 | 214 | // Try to decode QR code 215 | val reader = MultiFormatReader() 216 | val hints = mapOf( 217 | DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE), 218 | DecodeHintType.TRY_HARDER to true 219 | ) 220 | 221 | try { 222 | val result = reader.decode(binaryBitmap, hints) 223 | return result.text 224 | } catch (e: NotFoundException) { 225 | // No QR code found 226 | Log.d("MainActivity", "No QR code found in image") 227 | return "" 228 | } 229 | } finally { 230 | bitmap.recycle() 231 | } 232 | } 233 | return "" 234 | } 235 | 236 | internal fun processArchiveUrl(url: String): String { 237 | val uri = Uri.parse(url) 238 | val pattern = Regex("archive\\.[a-z]+/o/[a-zA-Z0-9]+/(.+)") 239 | val matchResult = pattern.find(uri.toString()) 240 | 241 | return if (matchResult != null) { 242 | matchResult.groupValues[1] 243 | } else { 244 | url 245 | } 246 | } 247 | 248 | // Keep for fallback purposes 249 | private fun isTrackingParam(param: String): Boolean { 250 | val trackingParams = setOf( 251 | "utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term", 252 | "fbclid", "gclid", "dclid", "gbraid", "wbraid", "msclkid", "tclid", 253 | "aff_id", "affiliate_id", "ref", "referer", "campaign_id", "ad_id", 254 | "adgroup_id", "adset_id", "creativetype", "placement", "network", 255 | "mc_eid", "mc_cid", "si", "icid", "_ga", "_gid", "scid", "click_id", 256 | "trk", "track", "trk_sid", "sid", "mibextid", "fb_action_ids", 257 | "fb_action_types", "twclid", "igshid", "s_kwcid", "sxsrf", "sca_esv", 258 | "source", "tbo", "sa", "ved", "pi", "fbs", "fbc", "fb_ref", "client", "ei", 259 | "gs_lp", "sclient", "oq", "uact", "bih", "biw", // sxsrf might be needed on some sites, but google uses it for tracking 260 | "m_entstream_source", "entstream_source", "fb_source", 261 | "ref_source", "ref_medium", "ref_campaign", "ref_content", "ref_term", "ref_keyword", 262 | "ref_type", "ref_campaign_id", "ref_ad_id", "ref_adgroup_id", "ref_adset_id", 263 | "ref_creativetype", "ref_placement", "ref_network", "ref_sid", "ref_mc_eid", 264 | "ref_mc_cid", "ref_scid", "ref_click_id", "ref_trk", "ref_track", "ref_trk_sid", 265 | "ref_sid", "ref", "ref_url", "ref_campaign_id", "ref_ad_id", "ref_adgroup_id", "ref_adset_id" 266 | ) 267 | return param in trackingParams 268 | } 269 | 270 | internal fun isUnwantedYoutubeParam(param: String): Boolean { 271 | val youtubeParams = setOf( 272 | "feature", 273 | "ab_channel", 274 | "t", 275 | "si" 276 | ) 277 | return param in youtubeParams 278 | } 279 | internal fun isUnwantedSubstackParam(param: String): Boolean { 280 | val substackParams = setOf( 281 | "r", 282 | "showWelcomeOnShare" 283 | ) 284 | return param in substackParams 285 | } 286 | 287 | // Keep for fallback and special handling 288 | internal fun cleanTrackingParamsFromUrl(url: String): String { 289 | val uri = Uri.parse(url) 290 | if (uri.legacyGetQueryParameterNames().isEmpty()) { 291 | return url 292 | } 293 | 294 | val newUriBuilder = uri.buildUpon().legacyClearQuery() 295 | var removeYouTubeParams = false 296 | var removeSubstackParams = false 297 | 298 | // Additional handling for YouTube URLs 299 | if (uri.host?.contains("youtube.com") == true || uri.host?.contains("youtu.be") == true) { 300 | removeYouTubeParams = true 301 | val nestedQueryParams = uri.getQueryParameter("q") 302 | if (nestedQueryParams != null) { 303 | val nestedUri = Uri.parse(nestedQueryParams) 304 | val newNestedUriBuilder = nestedUri.buildUpon().legacyClearQuery() 305 | 306 | nestedUri.legacyGetQueryParameterNames().forEach { nestedParam -> 307 | if (!isTrackingParam(nestedParam)) { 308 | newNestedUriBuilder.appendQueryParameter(nestedParam, nestedUri.getQueryParameter(nestedParam)) 309 | } 310 | } 311 | newUriBuilder.appendQueryParameter("q", newNestedUriBuilder.build().toString()) 312 | } 313 | } 314 | 315 | else if(uri.host?.endsWith(".substack.com") == true) { 316 | removeSubstackParams = true 317 | } 318 | 319 | uri.legacyGetQueryParameterNames().forEach { param -> 320 | // Add only non-tracking parameters to the new URL 321 | if (!isTrackingParam(param) && !(removeYouTubeParams && isUnwantedYoutubeParam(param)) && !(removeSubstackParams && isUnwantedSubstackParam(param))) { 322 | newUriBuilder.appendQueryParameter(param, uri.getQueryParameter(param)) 323 | } 324 | } 325 | return newUriBuilder.build().toString() 326 | } 327 | 328 | internal fun extractUrl(text: String): String? { 329 | // First try to find URLs with protocols 330 | val protocolMatcher = WebURLMatcher.matcher(text) 331 | if (protocolMatcher.find()) { 332 | return cleanUrl(protocolMatcher.group(0)) 333 | } 334 | 335 | // If no URL with protocol is found, look for potential bare domains 336 | val domainPattern = Regex( 337 | "(?:^|\\s+)(" + // Start of string or whitespace 338 | "(?:[a-zA-Z0-9][a-zA-Z0-9-]*\\.)+?" + // Subdomains and domain name 339 | "[a-zA-Z]{2,}" + // TLD 340 | "(?:/[^\\s]*)?" + // Optional path 341 | ")(?:\\s+|\$)" // End of string or whitespace 342 | ) 343 | 344 | val domainMatch = domainPattern.find(text) 345 | if (domainMatch != null) { 346 | val bareUrl = domainMatch.groupValues[1].trim() 347 | // Add https:// prefix and clean the URL 348 | return cleanUrl("https://$bareUrl") 349 | } 350 | 351 | return null 352 | } 353 | 354 | internal fun cleanUrl(url: String): String { 355 | val cleanedUrl = if (!url.startsWith("http://") && !url.startsWith("https://")) { 356 | val lastHttpsIndex = url.lastIndexOf("https://") 357 | val lastHttpIndex = url.lastIndexOf("http://") 358 | val lastValidUrlIndex = maxOf(lastHttpsIndex, lastHttpIndex) 359 | 360 | if (lastValidUrlIndex != -1) { 361 | // Extract the portion from the last valid protocol and clean any remaining %09 sequences 362 | url.substring(lastValidUrlIndex).replace(Regex("%09+"), "") 363 | } else { 364 | // If no valid protocol is found, add https:// and clean %09 sequences 365 | "https://${url.replace(Regex("%09+"), "")}" 366 | } 367 | } else { 368 | // URL already starts with a protocol, just clean %09 sequences 369 | url.replace(Regex("%09+"), "") 370 | } 371 | 372 | // Remove any trailing punctuation that might have been caught 373 | return cleanedUrl 374 | .removeSuffix(".") 375 | .removeSuffix(",") 376 | .removeSuffix(";") 377 | .removeSuffix(")") 378 | .removeSuffix("'") 379 | .removeSuffix("\"") 380 | } 381 | 382 | open fun openInBrowser(url: String) { 383 | Log.d("MainActivity", "Opening URL: $url") 384 | val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) 385 | startActivity(browserIntent) 386 | finish() 387 | } 388 | } -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/java/org/gnosco/share2archivetoday/WebURLMatcher.kt: -------------------------------------------------------------------------------- 1 | import java.util.regex.Matcher 2 | import java.util.regex.Pattern 3 | 4 | object WebURLMatcher { 5 | private val IP_ADDRESS 6 | : Pattern = Pattern.compile( 7 | "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" 8 | + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" 9 | + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" 10 | + "|[1-9][0-9]|[0-9]))" 11 | ) 12 | 13 | /** 14 | * Valid UCS characters defined in RFC 3987. Excludes space characters. 15 | */ 16 | private val UCS_CHAR = ("[" + 17 | "\u00A0-\uD7FF" + 18 | "\uF900-\uFDCF" + 19 | "\uFDF0-\uFFEF" + 20 | "\uD800\uDC00-\uD83F\uDFFD" + 21 | "\uD840\uDC00-\uD87F\uDFFD" + 22 | "\uD880\uDC00-\uD8BF\uDFFD" + 23 | "\uD8C0\uDC00-\uD8FF\uDFFD" + 24 | "\uD900\uDC00-\uD93F\uDFFD" + 25 | "\uD940\uDC00-\uD97F\uDFFD" + 26 | "\uD980\uDC00-\uD9BF\uDFFD" + 27 | "\uD9C0\uDC00-\uD9FF\uDFFD" + 28 | "\uDA00\uDC00-\uDA3F\uDFFD" + 29 | "\uDA40\uDC00-\uDA7F\uDFFD" + 30 | "\uDA80\uDC00-\uDABF\uDFFD" + 31 | "\uDAC0\uDC00-\uDAFF\uDFFD" + 32 | "\uDB00\uDC00-\uDB3F\uDFFD" + 33 | "\uDB44\uDC00-\uDB7F\uDFFD" + 34 | "&&[^\u00A0[\u2000-\u200A]\u2028\u2029\u202F\u3000]]") 35 | 36 | /** 37 | * Valid characters for IRI label defined in RFC 3987. 38 | */ 39 | private val LABEL_CHAR = "a-zA-Z0-9" + UCS_CHAR 40 | 41 | /** 42 | * Valid characters for IRI TLD defined in RFC 3987. 43 | */ 44 | private val TLD_CHAR = "a-zA-Z" + UCS_CHAR 45 | 46 | /** 47 | * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets. 48 | */ 49 | private val IRI_LABEL = 50 | "[" + LABEL_CHAR + "](?:[" + LABEL_CHAR + "_\\-]{0,61}[" + LABEL_CHAR + "]){0,1}" 51 | 52 | /** 53 | * RFC 3492 references RFC 1034 and limits Punycode algorithm output to 63 characters. 54 | */ 55 | private val PUNYCODE_TLD = "xn\\-\\-[\\w\\-]{0,58}\\w" 56 | private val TLD = "(" + PUNYCODE_TLD + "|" + "[" + TLD_CHAR + "]{2,63}" + ")" 57 | private val HOST_NAME = "(" + IRI_LABEL + "\\.)+" + TLD 58 | val DOMAIN_NAME 59 | : Pattern = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")") 60 | private val PROTOCOL = "(?i:http|https|rtsp)://" 61 | 62 | /* A word boundary or end of input. This is to stop foo.sure from matching as foo.su */ 63 | private val WORD_BOUNDARY = "(?:\\b|$|^)" 64 | private val USER_INFO = (("(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" 65 | + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" 66 | + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@")) 67 | private val PORT_NUMBER = "\\:\\d{1,5}" 68 | private val PATH_AND_QUERY = ("[/\\?](?:(?:[" + LABEL_CHAR 69 | + ";/\\?:@&=#~" // plus optional query params 70 | + "\\-\\.\\+!\\*'\\(\\),_\\$])|(?:%[a-fA-F0-9]{2}))*") 71 | 72 | /** 73 | * Regular expression pattern to match most part of RFC 3987 74 | * Internationalized URLs, aka IRIs. 75 | */ 76 | private val WEB_URL: Pattern = Pattern.compile( 77 | (("(" 78 | + "(" 79 | + "(?:" + PROTOCOL + "(?:" + USER_INFO + ")?" + ")?" 80 | + "(?:" + DOMAIN_NAME + ")" 81 | + "(?:" + PORT_NUMBER + ")?" 82 | + ")" 83 | + "(" + PATH_AND_QUERY + ")?" 84 | + WORD_BOUNDARY 85 | + ")")) 86 | ) 87 | 88 | fun matcher(text: String): Matcher { 89 | return WEB_URL.matcher(text) 90 | } 91 | } -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/play_store_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabefair/Share-2-Archive-Today/40d2b86f32cbf913f6d6619546fc80d5afca9aa2/Share2ArchiveToday/app/src/main/res/play_store_512.png -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-af/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Deel met Argief Vandag 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-am/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | አካባቢ ወደ ማህደር ዛሬ 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-ar/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | شارك للأرشيف 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-az-rAZ/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Bu gün Arxivə Paylaş 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-be/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Падзяліцца ў Архіў Сёння 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-bg/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Сподели към Архив Днес 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-bn-rBD/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | আজ আর্কাইভে শেয়ার করুন 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-ca/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Comparteix a l\'Arxiu Avui 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-cs-rCZ/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Sdílet do Archivu Dnes 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-da-rDK/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Del til Arkiv I Dag 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-de/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Share 2 Archive Today 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-el-rGR/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Μοιράσου στο Αρχείο Σήμερα 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-et/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Jaga Arhiivi Täna 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-eu-rES/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Parteka Artxiboa Gaur 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-fi-rFI/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Jaa Arkistoon Tänään 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-fil/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Ibahagi sa Archive Ngayon 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-fr-rCA/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Partage à l\'Archive 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-fr-rFR/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Partage à l\'Archive 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-gl-rES/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Comparte no Arquivo Hoxe 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-gu/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | આજે શેર કરો આર્કાઇવ માટે 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-hi/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | आज ही साझा करें आर्काइव में 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-hr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Podijeli u Arhivu Danas 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-hy-rAM/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Կիսվիր Արխիվի հետ այսօր 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-iw/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | שתף לארכיון היום 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-ka/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | გააზიარე არქივში დღესვე 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-my-rMM/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ယနေ့ သိုလှောင်ရန် မျှဝေပါ 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-nl-rNL/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Deel met Archief Vandaag 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-sq/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Ndaj tek Arkiva Sot 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 一键分享存档 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-zh-rHK/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 一鍵分享存檔 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values-zh-rTW/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 一鍵分享存檔 3 | 4 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Share 2 Archive Today 3 | -------------------------------------------------------------------------------- /Share2ArchiveToday/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |