mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d8953bf4e | |||
| 375cc978c5 | |||
| 0f4399bb62 | |||
| 00fb8c7d29 | |||
| ab271225de | |||
| 9180344043 | |||
| c5a2f6e311 | |||
| 4780c9bd6f | |||
| 6350ab6752 | |||
| f6cf33b996 | |||
| 9872f4da2b | |||
| b6fd93eae5 | |||
| 85316bec3f | |||
| 1935653309 | |||
| e3e24b4a06 | |||
| 7af53dcc18 | |||
| 2eb0ab0f19 | |||
| 07857a53c2 | |||
| 25fd31e252 |
@@ -1,4 +1,6 @@
|
||||
name: Build
|
||||
name: build
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -20,7 +22,7 @@ on:
|
||||
default: fdroid
|
||||
options:
|
||||
- fdroid
|
||||
- full
|
||||
- standalone
|
||||
secrets:
|
||||
SIGNING_KEY_ALIAS:
|
||||
required: false
|
||||
@@ -94,10 +96,7 @@ jobs:
|
||||
run: |
|
||||
store_path=${{ env.KEY_STORE_LOCATION }}${{ env.KEY_STORE_FILE }}
|
||||
echo "KEY_STORE_PATH=$store_path" >> $GITHUB_ENV
|
||||
- name: Create service_account.json
|
||||
if: ${{ inputs.build_type != 'debug' }}
|
||||
id: createServiceAccount
|
||||
run: echo '${{ secrets.SERVICE_ACCOUNT_JSON }}' > service_account.json
|
||||
|
||||
- name: Build APK
|
||||
run: |
|
||||
flavor=${{ inputs.flavor }}
|
||||
@@ -123,6 +122,6 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: android_artifacts_${{ inputs.flavor }}
|
||||
path: app/build/outputs/apk/${{ inputs.flavor }}/release/wgtunnel-${{ inputs.flavor }}-release-*.apk
|
||||
path: app/build/outputs/apk/${{ inputs.flavor }}/${{ inputs.build_type }}/wgtunnel-${{ inputs.flavor }}${{ inputs.flavor == 'fdroid' && '-release' || '' }}-*.apk
|
||||
retention-days: 1
|
||||
if-no-files-found: warn
|
||||
@@ -0,0 +1,127 @@
|
||||
name: nightly
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "4 3 * * *"
|
||||
|
||||
jobs:
|
||||
check_commits:
|
||||
name: Check for New Commits
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
has_new_commits: ${{ steps.check.outputs.new_commits }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Check for new commits
|
||||
id: check
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
||||
run: |
|
||||
NEW_COMMITS=$(git rev-list --count --after="$(date -Iseconds -d '23 hours ago')" ${{ github.sha }})
|
||||
echo "new_commits=$NEW_COMMITS" >> $GITHUB_OUTPUT
|
||||
|
||||
build-standalone-nightly:
|
||||
uses: ./.github/workflows/build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
build_type: "nightly"
|
||||
flavor: standalone
|
||||
|
||||
publish:
|
||||
needs:
|
||||
- check_commits
|
||||
- build-standalone-nightly
|
||||
if: ${{ needs.check_commits.outputs.has_new_commits > 0 && inputs.release_type != 'none' }}
|
||||
name: publish-nightly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt update && sudo apt install -y gh apksigner
|
||||
- name: Set latest tag
|
||||
uses: rickstaa/action-create-tag@v1
|
||||
id: tag_creation
|
||||
with:
|
||||
tag: "latest"
|
||||
message: "Automated tag for HEAD commit"
|
||||
force_push_tag: true
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag_exists_error: false
|
||||
|
||||
- name: Generate Changelog
|
||||
id: changelog
|
||||
uses: requarks/changelog-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
toTag: "nightly"
|
||||
fromTag: "latest"
|
||||
writeToFile: false
|
||||
|
||||
- name: Make download dir
|
||||
run: mkdir ${{ github.workspace }}/temp
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: android_artifacts_*
|
||||
path: ${{ github.workspace }}/temp
|
||||
|
||||
- name: Set release notes
|
||||
run: |
|
||||
echo "RELEASE_NOTES=Nightly build for the latest development version of the app." >> $GITHUB_ENV
|
||||
|
||||
- name: Delete previous nightly version
|
||||
uses: ClementTsang/delete-tag-and-release@v0.4.0
|
||||
with:
|
||||
tag_name: "nightly"
|
||||
delete_release: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get checksum
|
||||
id: checksum
|
||||
run: |
|
||||
file_path=$(find ${{ github.workspace }}/temp -type f -iname "*.apk" | head -n 1)
|
||||
if [ -z "$file_path" ]; then
|
||||
echo "No APK file found"
|
||||
exit 1
|
||||
fi
|
||||
checksum=$(apksigner verify --print-certs "$file_path" | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")
|
||||
echo "checksum=$checksum" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create nightly release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
body: |
|
||||
${{ env.RELEASE_NOTES }}
|
||||
|
||||
SHA-256 fingerprints for the 4096-bit signing certificate:
|
||||
```sh
|
||||
${{ steps.checksum.outputs.checksum }}
|
||||
```
|
||||
|
||||
To verify fingerprint:
|
||||
```sh
|
||||
apksigner verify --print-certs [path to APK file] | grep SHA-256
|
||||
```
|
||||
|
||||
### Changelog
|
||||
${{ steps.changelog.outputs.changes }}
|
||||
tag_name: nightly
|
||||
name: nightly
|
||||
draft: false
|
||||
prerelease: true
|
||||
make_latest: false
|
||||
files: |
|
||||
${{ github.workspace }}/temp/**/*.apk
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,4 +1,6 @@
|
||||
name: on-pr
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
name: publish
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "4 3 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
track:
|
||||
@@ -22,95 +23,60 @@ on:
|
||||
options:
|
||||
- none
|
||||
- prerelease
|
||||
- nightly
|
||||
- release
|
||||
default: release
|
||||
required: true
|
||||
tag_name:
|
||||
description: "Tag name for release"
|
||||
required: false
|
||||
default: nightly
|
||||
default: 1.1.1
|
||||
flavor:
|
||||
type: choice
|
||||
description: "Product flavor"
|
||||
required: true
|
||||
default: full
|
||||
default: standalone
|
||||
options:
|
||||
- fdroid
|
||||
- full
|
||||
- standalone
|
||||
workflow_call:
|
||||
inputs:
|
||||
flavor:
|
||||
type: string
|
||||
description: "Product flavor"
|
||||
required: false
|
||||
default: full
|
||||
|
||||
env:
|
||||
UPLOAD_DIR_ANDROID: android_artifacts
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
default: standalone
|
||||
|
||||
jobs:
|
||||
check_commits:
|
||||
name: Check for New Commits
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
has_new_commits: ${{ steps.check.outputs.new_commits }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check for new commits
|
||||
id: check
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
||||
run: |
|
||||
NEW_COMMITS=$(git rev-list --count --after="$(date -Iseconds -d '23 hours ago')" ${{ github.sha }})
|
||||
echo "new_commits=$NEW_COMMITS" >> $GITHUB_OUTPUT
|
||||
|
||||
build-fdroid:
|
||||
if: ${{ inputs.release_type == 'release' || inputs.flavor == 'fdroid' }}
|
||||
uses: ./.github/workflows/build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
build_type: ${{ inputs.release_type == '' && 'nightly' || inputs.release_type }}
|
||||
build_type: ${{ inputs.release_type }}
|
||||
flavor: fdroid
|
||||
|
||||
build-full:
|
||||
if: ${{ inputs.release_type == 'release' || inputs.release_type == 'nightly' || inputs.release_type == 'prerelease' || inputs.flavor == 'full' }}
|
||||
build-standalone:
|
||||
if: ${{ inputs.release_type == 'release' || inputs.release_type == 'prerelease' || inputs.flavor == 'standalone' }}
|
||||
uses: ./.github/workflows/build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
build_type: ${{ inputs.release_type == '' && 'nightly' || inputs.release_type }}
|
||||
flavor: full
|
||||
build_type: ${{ inputs.release_type }}
|
||||
flavor: standalone
|
||||
|
||||
publish:
|
||||
needs:
|
||||
- check_commits
|
||||
- build-full
|
||||
if: ${{ needs.check_commits.outputs.has_new_commits > 0 && inputs.release_type != 'none' }}
|
||||
- build-standalone
|
||||
name: publish-github
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: main
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt update && sudo apt install -y gh apksigner
|
||||
- name: Set TAG_NAME
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "TAG_NAME=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV
|
||||
elif [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
echo "TAG_NAME=nightly" >> $GITHUB_ENV
|
||||
echo "RELEASE_TYPE=nightly" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Set latest tag
|
||||
uses: rickstaa/action-create-tag@v1
|
||||
id: tag_creation
|
||||
@@ -126,22 +92,26 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
latest: true
|
||||
|
||||
- name: Generate Changelog
|
||||
id: changelog
|
||||
uses: requarks/changelog-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
toTag: ${{ github.event_name == 'schedule' && 'nightly' || steps.latest_release.outputs.tag_name }}
|
||||
toTag: ${{ steps.latest_release.outputs.tag_name }}
|
||||
fromTag: "latest"
|
||||
writeToFile: false
|
||||
|
||||
- name: Make download dir
|
||||
run: mkdir ${{ github.workspace }}/temp
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: android_artifacts_*
|
||||
path: ${{ github.workspace }}/temp
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set version release notes
|
||||
if: ${{ inputs.release_type == 'release' }}
|
||||
run: |
|
||||
@@ -151,36 +121,22 @@ jobs:
|
||||
echo "$RELEASE_NOTES" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
- name: On nightly release notes
|
||||
if: ${{ contains(env.TAG_NAME, 'nightly') }}
|
||||
run: |
|
||||
echo "RELEASE_NOTES=Nightly build for the latest development version of the app." >> $GITHUB_ENV
|
||||
|
||||
- name: On prerelease release notes
|
||||
if: ${{ inputs.release_type == 'prerelease' }}
|
||||
run: |
|
||||
echo "RELEASE_NOTES=Testing version of app for specific feature." >> $GITHUB_ENV
|
||||
|
||||
- name: Delete previous release
|
||||
if: ${{ contains(env.TAG_NAME, 'nightly') || inputs.release_type == 'prerelease' }}
|
||||
uses: ClementTsang/delete-tag-and-release@v0.4.0
|
||||
with:
|
||||
tag_name: ${{ env.TAG_NAME }}
|
||||
delete_release: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get checksums
|
||||
- name: Get checksum
|
||||
id: checksum
|
||||
run: |
|
||||
checksums=""
|
||||
for file_path in $(find ${{ github.workspace }}/temp -type f -iname "*.apk"); do
|
||||
checksum=$(apksigner verify -print-certs $file_path | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")
|
||||
checksums="$checksums\n$file_path: $checksum"
|
||||
done
|
||||
echo "checksum<<EOF" >> $GITHUB_OUTPUT
|
||||
echo -e "$checksums" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
file_path=$(find ${{ github.workspace }}/temp -type f -iname "*.apk" | head -n 1)
|
||||
if [ -z "$file_path" ]; then
|
||||
echo "No APK file found"
|
||||
exit 1
|
||||
fi
|
||||
checksum=$(apksigner verify --print-certs "$file_path" | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")
|
||||
echo "checksum=$checksum" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v2
|
||||
@@ -200,13 +156,13 @@ jobs:
|
||||
|
||||
### Changelog
|
||||
${{ steps.changelog.outputs.changes }}
|
||||
tag_name: ${{ env.TAG_NAME }}
|
||||
name: ${{ env.TAG_NAME }}
|
||||
tag_name: ${{ github.event.inputs.tag_name }}
|
||||
name: ${{ github.event.inputs.tag_name }}
|
||||
draft: false
|
||||
prerelease: ${{ inputs.release_type == 'prerelease' || inputs.release_type == '' || inputs.release_type == 'nightly' }}
|
||||
prerelease: ${{ inputs.release_type == 'prerelease' }}
|
||||
make_latest: ${{ inputs.release_type == 'release' }}
|
||||
files: |
|
||||
${{ github.workspace }}/temp/*
|
||||
${{ github.workspace }}/temp/**/*.apk
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -224,7 +180,7 @@ jobs:
|
||||
event-type: fdroid-update
|
||||
|
||||
publish-play:
|
||||
if: ${{ inputs.track != 'none' && inputs.track != '' }}
|
||||
if: ${{ inputs.track != 'none' }}
|
||||
name: Publish to Google Play
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
@@ -103,7 +103,10 @@ android {
|
||||
dimension = "type"
|
||||
buildConfigField("String", "FLAVOR", "\"google\"")
|
||||
}
|
||||
create("full") { dimension = "type" }
|
||||
create("standalone") {
|
||||
dimension = "type"
|
||||
buildConfigField("String", "FLAVOR", "\"standalone\"")
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
||||
@@ -168,7 +168,6 @@
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.USER_PRESENT" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||
|
||||
@@ -134,6 +134,7 @@ class MainActivity : AppCompatActivity() {
|
||||
vpnPermissionDenied = true
|
||||
} else {
|
||||
vpnPermissionDenied = false
|
||||
showVpnPermissionDialog = false
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -208,7 +209,10 @@ class MainActivity : AppCompatActivity() {
|
||||
WireguardAutoTunnelTheme(theme = appUiState.appState.theme) {
|
||||
VpnDeniedDialog(
|
||||
showVpnPermissionDialog,
|
||||
onDismiss = { showVpnPermissionDialog = false },
|
||||
onDismiss = {
|
||||
showVpnPermissionDialog = false
|
||||
vpnPermissionDenied = false
|
||||
},
|
||||
)
|
||||
|
||||
Scaffold(
|
||||
|
||||
+4
-4
@@ -3,12 +3,12 @@ package com.zaneschepke.wireguardautotunnel.core.broadcast
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.zaneschepke.logcatter.LogReader
|
||||
import com.zaneschepke.wireguardautotunnel.core.service.ServiceManager
|
||||
import com.zaneschepke.wireguardautotunnel.core.tunnel.TunnelManager
|
||||
import com.zaneschepke.wireguardautotunnel.di.ApplicationScope
|
||||
import com.zaneschepke.wireguardautotunnel.di.IoDispatcher
|
||||
import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.isRunningOnTv
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
@@ -26,13 +26,12 @@ class RestartReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var tunnelManager: TunnelManager
|
||||
|
||||
@Inject lateinit var logReader: LogReader
|
||||
|
||||
@Inject @IoDispatcher lateinit var ioDispatcher: CoroutineDispatcher
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Timber.d("RestartReceiver triggered with action: ${intent.action}")
|
||||
// screen on for Android TV only to help with sleep shutdowns
|
||||
val isTv = context.isRunningOnTv()
|
||||
if (intent.action == Intent.ACTION_USER_PRESENT && !isTv) return
|
||||
serviceManager.updateTunnelTile()
|
||||
serviceManager.updateAutoTunnelTile()
|
||||
applicationScope.launch(ioDispatcher) {
|
||||
@@ -50,6 +49,7 @@ class RestartReceiver : BroadcastReceiver() {
|
||||
} else {
|
||||
Timber.d("Restore on boot disabled, skipping")
|
||||
}
|
||||
if (intent.action == Intent.ACTION_MY_PACKAGE_REPLACED) logReader.deleteAndClearLogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -165,8 +165,12 @@ class TunnelForegroundService : LifecycleService() {
|
||||
} else {
|
||||
pingJobs[tun]?.cancel() // Cancel any stale job
|
||||
if (tun.isPingEnabled) {
|
||||
pingJobs[tun] = startPingJob(tun)
|
||||
Timber.d("Started ping job for ${tun.tunName}")
|
||||
if (tun.isStaticallyConfigured()) {
|
||||
Timber.d("Skipping ping for statically configured tunnel")
|
||||
} else {
|
||||
pingJobs[tun] = startPingJob(tun)
|
||||
Timber.d("Started ping job for ${tun.tunName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,10 @@ data class TunnelConf(
|
||||
return result
|
||||
}
|
||||
|
||||
fun isStaticallyConfigured(): Boolean {
|
||||
return toAmConfig().peers.all { it.endpoint.get().host.isValidIpv4orIpv6Address() }
|
||||
}
|
||||
|
||||
fun copyWithCallback(
|
||||
id: Int = this.id,
|
||||
tunName: String = this.tunName,
|
||||
|
||||
+2
-1
@@ -52,8 +52,9 @@ fun InterfaceFields(
|
||||
if (isAuthenticated) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
enabled = isAuthenticated,
|
||||
enabled = true,
|
||||
onClick = {
|
||||
if (!isAuthenticated) return@IconButton showAuthPrompt()
|
||||
val keypair = com.wireguard.crypto.KeyPair()
|
||||
onInterfaceChange(
|
||||
interfaceState.copy(
|
||||
|
||||
+5
-3
@@ -23,6 +23,7 @@ import com.zaneschepke.wireguardautotunnel.ui.common.label.GroupLabel
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.support.components.ContactSupportOptions
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.support.components.GeneralSupportOptions
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.support.components.UpdateSection
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.canInstallPackages
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.openWebUrl
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.requestInstallPackagesPermission
|
||||
@@ -54,7 +55,7 @@ fun SupportScreen(viewModel: SupportViewModel = hiltViewModel(), appViewModel: A
|
||||
InfoDialog(
|
||||
onDismiss = { viewModel.handleUpdateShown() },
|
||||
onAttest = {
|
||||
if (BuildConfig.FLAVOR != "full") {
|
||||
if (BuildConfig.FLAVOR != Constants.STANDALONE_FLAVOR) {
|
||||
uiState.appUpdate?.apkUrl?.let { context.openWebUrl(it) }
|
||||
return@InfoDialog
|
||||
}
|
||||
@@ -86,7 +87,8 @@ fun SupportScreen(viewModel: SupportViewModel = hiltViewModel(), appViewModel: A
|
||||
},
|
||||
confirmText = {
|
||||
Text(
|
||||
if (BuildConfig.FLAVOR != "full") stringResource(R.string.download)
|
||||
if (BuildConfig.FLAVOR != Constants.STANDALONE_FLAVOR)
|
||||
stringResource(R.string.download)
|
||||
else stringResource(R.string.download_and_install)
|
||||
)
|
||||
},
|
||||
@@ -124,7 +126,7 @@ fun SupportScreen(viewModel: SupportViewModel = hiltViewModel(), appViewModel: A
|
||||
if (
|
||||
BuildConfig.DEBUG ||
|
||||
BuildConfig.VERSION_NAME.contains("beta") ||
|
||||
BuildConfig.FLAVOR == "google"
|
||||
BuildConfig.FLAVOR == Constants.GOOGLE_PLAY_FLAVOR
|
||||
)
|
||||
return@UpdateSection context.showToast(R.string.update_check_unsupported)
|
||||
context.showToast(R.string.checking_for_update)
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ fun ContactSupportOptions(context: android.content.Context) {
|
||||
),
|
||||
)
|
||||
)
|
||||
if (BuildConfig.FLAVOR == Constants.FDROID_FLAVOR) {
|
||||
if (BuildConfig.FLAVOR != Constants.GOOGLE_PLAY_FLAVOR) {
|
||||
add(
|
||||
SelectionItem(
|
||||
leadingIcon = Icons.Filled.Favorite,
|
||||
|
||||
@@ -35,5 +35,7 @@ object Constants {
|
||||
const val QR_CODE_NAME_PROPERTY = "# Name ="
|
||||
|
||||
const val FDROID_FLAVOR = "fdroid"
|
||||
const val GOOGLE_PLAY_FLAVOR = "google"
|
||||
const val STANDALONE_FLAVOR = "standalone"
|
||||
const val RELEASE = "release"
|
||||
}
|
||||
|
||||
+19
-4
@@ -1,14 +1,29 @@
|
||||
package com.zaneschepke.wireguardautotunnel.util.extensions
|
||||
|
||||
import java.util.regex.Pattern
|
||||
import timber.log.Timber
|
||||
|
||||
val hasNumberInParentheses = """^(.+?)\((\d+)\)$""".toRegex()
|
||||
|
||||
fun String.isValidIpv4orIpv6Address(): Boolean {
|
||||
val ipv4Pattern = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\$")
|
||||
val ipv6Pattern = Pattern.compile("^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}\$")
|
||||
return ipv4Pattern.matcher(this).matches() || ipv6Pattern.matcher(this).matches()
|
||||
val sanitized = removeSurrounding("[", "]")
|
||||
val ipv6Pattern =
|
||||
Regex(
|
||||
"(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:)" +
|
||||
"{1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]" +
|
||||
"{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:" +
|
||||
"[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4})" +
|
||||
"{1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}" +
|
||||
":((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]" +
|
||||
"{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}" +
|
||||
"[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:)" +
|
||||
"{1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
|
||||
)
|
||||
val ipv4Pattern =
|
||||
Regex(
|
||||
"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}" +
|
||||
"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
||||
)
|
||||
return ipv4Pattern.matches(sanitized) || ipv6Pattern.matches(sanitized)
|
||||
}
|
||||
|
||||
fun String.hasNumberInParentheses(): Boolean {
|
||||
|
||||
@@ -6,7 +6,7 @@ androidx-junit = "1.2.1"
|
||||
appcompat = "1.7.0"
|
||||
biometricKtx = "1.2.0-alpha05"
|
||||
coreKtx = "1.16.0"
|
||||
datastorePreferences = "1.1.4"
|
||||
datastorePreferences = "1.2.0-alpha01"
|
||||
desugar_jdk_libs = "2.1.5"
|
||||
espressoCore = "3.6.1"
|
||||
hiltAndroid = "2.56.2"
|
||||
@@ -28,7 +28,8 @@ androidGradlePlugin = "8.9.2"
|
||||
kotlin = "2.1.20"
|
||||
ksp = "2.1.20-2.0.0"
|
||||
composeBom = "2025.04.01"
|
||||
compose = "1.7.8"
|
||||
compose = "1.8.0"
|
||||
icons = "1.7.8"
|
||||
workRuntimeKtxVersion = "2.10.1"
|
||||
zxingAndroidEmbedded = "4.3.0"
|
||||
coreSplashscreen = "1.0.1"
|
||||
@@ -95,7 +96,7 @@ ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktorCli
|
||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktorClientCore" }
|
||||
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktorClientCore" }
|
||||
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle-runtime-compose" }
|
||||
material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
|
||||
material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "icons" }
|
||||
|
||||
pin-lock-compose = { module = "com.zaneschepke:pin_lock_compose", version.ref = "pinLockCompose" }
|
||||
qrcode-kotlin = { module = "io.github.g0dkar:qrcode-kotlin", version.ref = "qrcodeKotlin" }
|
||||
|
||||
Reference in New Issue
Block a user