Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1bcfbebbd | |||
| 6b23b57415 | |||
| 2fccc8b985 | |||
| e0dd33a1db | |||
| 0a65c17e4e | |||
| 6bb9b97e91 | |||
| 5ff42b83e8 | |||
| b944ce9e93 | |||
| 947317c6a7 | |||
| 588b132853 | |||
| 3a7b9cae32 |
@@ -0,0 +1,173 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
Guidance for agentic coding tools working in `moasdawiki-app`.
|
||||||
|
|
||||||
|
## Project Snapshot
|
||||||
|
|
||||||
|
- Android app module: `:app`
|
||||||
|
- Language: Java 17 (no Kotlin sources currently)
|
||||||
|
- Build system: Gradle wrapper (`./gradlew`) + Android Gradle Plugin
|
||||||
|
- Main package: `net.moasdawiki.app`
|
||||||
|
- App depends on MoasdaWiki server module artifact: `net.moasdawiki:moasdawiki-server`
|
||||||
|
|
||||||
|
## Environment And Baseline
|
||||||
|
|
||||||
|
- Use the wrapper, not a globally installed Gradle: `./gradlew ...`
|
||||||
|
- Run commands from repository root.
|
||||||
|
- Keep changes scoped; do not refactor unrelated files.
|
||||||
|
- Preserve license headers in Java files.
|
||||||
|
- Prefer additive, minimal-risk edits.
|
||||||
|
|
||||||
|
## Build / Lint / Test Commands
|
||||||
|
|
||||||
|
### Common Lifecycle Commands
|
||||||
|
|
||||||
|
- Clean: `./gradlew clean`
|
||||||
|
- Build everything (assemble + checks): `./gradlew :app:build`
|
||||||
|
- Assemble debug APK: `./gradlew :app:assembleDebug`
|
||||||
|
- Assemble release APK: `./gradlew :app:assembleRelease`
|
||||||
|
- Install debug on connected device: `./gradlew :app:installDebug`
|
||||||
|
|
||||||
|
### Lint Commands
|
||||||
|
|
||||||
|
- Run lint (default variant): `./gradlew :app:lint`
|
||||||
|
- Run debug lint only: `./gradlew :app:lintDebug`
|
||||||
|
- Run release lint only: `./gradlew :app:lintRelease`
|
||||||
|
- Apply safe lint fixes: `./gradlew :app:lintFix`
|
||||||
|
|
||||||
|
### Unit Test Commands
|
||||||
|
|
||||||
|
- Run all unit tests: `./gradlew :app:test`
|
||||||
|
- Run debug unit tests: `./gradlew :app:testDebugUnitTest`
|
||||||
|
- Run release unit tests: `./gradlew :app:testReleaseUnitTest`
|
||||||
|
|
||||||
|
### Run A Single Unit Test (Important)
|
||||||
|
|
||||||
|
- Single test class:
|
||||||
|
`./gradlew :app:testDebugUnitTest --tests "net.moasdawiki.app.YourTestClass"`
|
||||||
|
- Single test method:
|
||||||
|
`./gradlew :app:testDebugUnitTest --tests "net.moasdawiki.app.YourTestClass.yourTestMethod"`
|
||||||
|
- Wildcard match:
|
||||||
|
`./gradlew :app:testDebugUnitTest --tests "*YourTestClass*"`
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Use fully-qualified class names for reliable filtering.
|
||||||
|
- If the filter reports no tests found, verify package + method names.
|
||||||
|
- Keep `Debug` test task unless you specifically need release behavior.
|
||||||
|
|
||||||
|
### Instrumentation Test Commands
|
||||||
|
|
||||||
|
- Run all connected instrumentation tests:
|
||||||
|
`./gradlew :app:connectedDebugAndroidTest`
|
||||||
|
- Run one instrumentation class:
|
||||||
|
`./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=net.moasdawiki.app.YourAndroidTestClass`
|
||||||
|
- Run one instrumentation method:
|
||||||
|
`./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=net.moasdawiki.app.YourAndroidTestClass#yourTestMethod`
|
||||||
|
|
||||||
|
## High-Value Working Agreement
|
||||||
|
|
||||||
|
- Before editing, inspect nearby code and follow existing patterns.
|
||||||
|
- After editing, run the narrowest meaningful verification first.
|
||||||
|
- For behavior changes, prefer adding/updating tests when test infra exists.
|
||||||
|
- Do not introduce new build tools or formatting frameworks unless asked.
|
||||||
|
|
||||||
|
## Source Layout (Current)
|
||||||
|
|
||||||
|
- App code: `app/src/main/java/net/moasdawiki/app/`
|
||||||
|
- Resources: `app/src/main/res/`
|
||||||
|
- Manifest: `app/src/main/AndroidManifest.xml`
|
||||||
|
- Gradle module config: `app/build.gradle`
|
||||||
|
- Root build config: `build.gradle`, `settings.gradle`, `gradle.properties`
|
||||||
|
|
||||||
|
There are currently no `app/src/test` or `app/src/androidTest` files in this repository snapshot.
|
||||||
|
|
||||||
|
## Java Style Conventions To Follow
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
- 4-space indentation, no tabs.
|
||||||
|
- Opening brace on same line for classes/methods/control blocks.
|
||||||
|
- Keep methods reasonably focused; avoid large unrelated rewrites.
|
||||||
|
- Prefer one statement per line for readability.
|
||||||
|
- Preserve existing block comments and Javadoc style.
|
||||||
|
|
||||||
|
### Imports
|
||||||
|
|
||||||
|
- Use explicit imports; avoid wildcard imports.
|
||||||
|
- Group imports with blank lines by domain:
|
||||||
|
1) `android.*`
|
||||||
|
2) `androidx.*`
|
||||||
|
3) `net.moasdawiki.*`
|
||||||
|
4) `java.*`
|
||||||
|
- Keep import order stable and consistent within each group.
|
||||||
|
|
||||||
|
### Types And Nullability
|
||||||
|
|
||||||
|
- Use concrete types unless abstraction improves clarity.
|
||||||
|
- Follow existing nullability annotations (`@NonNull`, `@Nullable`).
|
||||||
|
- Annotate parameters/returns where null-safety is non-obvious.
|
||||||
|
- Prefer immutable locals/fields (`final`) where practical.
|
||||||
|
- Use boxed types only when null is a real state.
|
||||||
|
|
||||||
|
### Naming
|
||||||
|
|
||||||
|
- Classes: `PascalCase` (`MainActivity`, `SynchronizeWikiClient`).
|
||||||
|
- Methods/fields/local variables: `camelCase`.
|
||||||
|
- Constants: `UPPER_SNAKE_CASE`.
|
||||||
|
- Android log tags: short static constant named `TAG`.
|
||||||
|
- Preference keys/constants belong in `Constants`-style central locations.
|
||||||
|
|
||||||
|
### Control Flow And Readability
|
||||||
|
|
||||||
|
- Prefer early returns for invalid preconditions.
|
||||||
|
- Keep nesting shallow when possible.
|
||||||
|
- Extract helper methods for repeated logic.
|
||||||
|
- Use descriptive method names that reflect side effects.
|
||||||
|
|
||||||
|
### Error Handling And Logging
|
||||||
|
|
||||||
|
- Catch specific exceptions whenever practical.
|
||||||
|
- Log with Android `Log` at appropriate level (`d`, `i`, `w`, `e`).
|
||||||
|
- Include exception object when logging failures.
|
||||||
|
- Convert low-level failures into domain-friendly outcomes for callers.
|
||||||
|
- For user-visible failures, pair logs with UI feedback (`Toast`/status text).
|
||||||
|
- Avoid swallowing exceptions silently.
|
||||||
|
|
||||||
|
### Threading / Android Behavior
|
||||||
|
|
||||||
|
- Keep network and disk work off the UI thread.
|
||||||
|
- UI updates must run on UI thread (`runOnUiThread(...)` pattern).
|
||||||
|
- Continue using executor-based async style already present.
|
||||||
|
- Preserve lifecycle-safe behavior in `Activity`/`Fragment` methods.
|
||||||
|
|
||||||
|
## Testing Expectations For Agents
|
||||||
|
|
||||||
|
- If you change pure logic, add or update a unit test.
|
||||||
|
- If you change Android component behavior, prefer instrumentation tests when feasible.
|
||||||
|
- For low-risk refactors, run at least targeted lint + targeted tests.
|
||||||
|
- For broader edits, run `:app:lint` and `:app:testDebugUnitTest`.
|
||||||
|
|
||||||
|
## Dependency And Build File Edits
|
||||||
|
|
||||||
|
- Keep dependency changes minimal and justified.
|
||||||
|
- Match existing dependency declaration style in touched file.
|
||||||
|
- Do not upgrade AGP/Gradle/SDK versions unless explicitly requested.
|
||||||
|
- Call out deprecation warnings you encounter during Gradle runs.
|
||||||
|
|
||||||
|
## Commit And PR Hygiene (For Agents)
|
||||||
|
|
||||||
|
- Make small, reviewable commits with clear intent.
|
||||||
|
- In commit messages, explain why the change is needed.
|
||||||
|
- Include verification commands run and their outcome in PR notes.
|
||||||
|
- Do not include unrelated formatting churn.
|
||||||
|
|
||||||
|
## Cursor/Copilot Rule Ingestion
|
||||||
|
|
||||||
|
Checked in this repository:
|
||||||
|
|
||||||
|
- `.cursorrules`: not present
|
||||||
|
- `.cursor/rules/`: not present
|
||||||
|
- `.github/copilot-instructions.md`: not present
|
||||||
|
|
||||||
|
If these files are added later, agents should treat them as higher-priority repository instructions and merge them into this guidance.
|
||||||
+9
-1
@@ -1,6 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 3.9.5.1 (versionCode 48, 2025-08-30)
|
## 3.9.7.0 (versionCode 50, 2026-01-02)
|
||||||
|
|
||||||
|
- Bugfix: Use back gesture for browser back
|
||||||
|
- Upgrade to moasdawiki-server 3.9.7
|
||||||
|
- Upgrade to Java 17
|
||||||
|
- Upgrade library dependencies
|
||||||
|
- Update copyright year
|
||||||
|
|
||||||
|
## 3.9.5.1 (versionCode 48 + 49, 2025-08-30)
|
||||||
|
|
||||||
- Bugfix: Searchbar not visible on newer Android versions
|
- Bugfix: Searchbar not visible on newer Android versions
|
||||||
- Shortened app name
|
- Shortened app name
|
||||||
|
|||||||
+13
-10
@@ -4,15 +4,15 @@ android {
|
|||||||
namespace = "net.moasdawiki.app"
|
namespace = "net.moasdawiki.app"
|
||||||
compileSdk = 36 // 36 = Android 16 Baklava
|
compileSdk = 36 // 36 = Android 16 Baklava
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "net.moasdawiki.app"
|
applicationId "space.hackenslacker.moasdawiki.app"
|
||||||
minSdk = 33 // 33 = Android 13 Tiramisu
|
minSdk = 29 // 29 = Android 10 Q
|
||||||
targetSdk = 36 // should be same as compileSdk
|
targetSdk = 36 // should be same as compileSdk
|
||||||
versionCode = 48
|
versionCode = 50
|
||||||
versionName = "3.9.5.1"
|
versionName = "3.9.7.0"
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_11
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
@@ -27,10 +27,13 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'net.moasdawiki:moasdawiki-server:3.9.5'
|
api 'net.moasdawiki:moasdawiki-server:3.9.7'
|
||||||
|
|
||||||
implementation ('androidx.appcompat:appcompat:1.7.1')
|
compileOnly 'androidx.annotation:annotation:1.3.0'
|
||||||
implementation ('androidx.preference:preference:1.2.1')
|
implementation 'androidx.appcompat:appcompat:1.7.1'
|
||||||
|
implementation 'androidx.preference:preference:1.2.1'
|
||||||
// Fix duplicate class error
|
// Fix duplicate class error
|
||||||
implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.10")
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.3.0"
|
||||||
|
|
||||||
|
testImplementation 'junit:junit:4.13.2'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:fullBackupContent="false"
|
android:fullBackupContent="false"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules">
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="net.moasdawiki.app.CalendarContentProvider"
|
android:name="net.moasdawiki.app.CalendarContentProvider"
|
||||||
android:authorities="net.moasdawiki.app.provider"
|
android:authorities="space.hackenslacker.moasdawiki.app.provider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:syncable="true"/>
|
android:syncable="true"/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
@@ -66,7 +66,7 @@ public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
|
|
||||||
static final String ACCOUNT_NAME = "MoasdaWiki";
|
static final String ACCOUNT_NAME = "MoasdaWiki";
|
||||||
static final String ACCOUNT_TYPE = "net.moasdawiki";
|
static final String ACCOUNT_TYPE = "net.moasdawiki";
|
||||||
static final String PROVIDER_NAME = "net.moasdawiki.app.provider";
|
static final String PROVIDER_NAME = "space.hackenslacker.moasdawiki.app.provider";
|
||||||
|
|
||||||
private static final String CALENDAR_NAME = "MoasdaWiki Events";
|
private static final String CALENDAR_NAME = "MoasdaWiki Events";
|
||||||
private static final Uri CALENDAR_URI = CalendarContract.Calendars.CONTENT_URI;
|
private static final Uri CALENDAR_URI = CalendarContract.Calendars.CONTENT_URI;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
@@ -44,13 +44,12 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.window.OnBackInvokedCallback;
|
|
||||||
import android.window.OnBackInvokedDispatcher;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.view.menu.MenuBuilder;
|
import androidx.appcompat.view.menu.MenuBuilder;
|
||||||
|
import androidx.activity.OnBackPressedCallback;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import net.moasdawiki.base.ServiceException;
|
import net.moasdawiki.base.ServiceException;
|
||||||
@@ -60,7 +59,6 @@ import net.moasdawiki.http.HttpRequest;
|
|||||||
import net.moasdawiki.server.RequestDispatcher;
|
import net.moasdawiki.server.RequestDispatcher;
|
||||||
import net.moasdawiki.service.HttpResponse;
|
import net.moasdawiki.service.HttpResponse;
|
||||||
import net.moasdawiki.service.repository.RepositoryService;
|
import net.moasdawiki.service.repository.RepositoryService;
|
||||||
import net.moasdawiki.util.EscapeUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -76,7 +74,7 @@ import java.util.concurrent.Executors;
|
|||||||
/**
|
/**
|
||||||
* Displays the main window with the embedded wiki browser.
|
* Displays the main window with the embedded wiki browser.
|
||||||
*/
|
*/
|
||||||
public class MainActivity extends AppCompatActivity implements OnBackInvokedCallback {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
private static final String SERVER_BASE_URL = "http://localhost:1/";
|
private static final String SERVER_BASE_URL = "http://localhost:1/";
|
||||||
@@ -116,7 +114,12 @@ public class MainActivity extends AppCompatActivity implements OnBackInvokedCall
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, this);
|
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
MainActivity.this.onBackInvoked();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,7 +395,11 @@ public class MainActivity extends AppCompatActivity implements OnBackInvokedCall
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private String getWikiserverSearchUrl(@NonNull String query) {
|
private String getWikiserverSearchUrl(@NonNull String query) {
|
||||||
return SERVER_BASE_URL + "search/?text=" + EscapeUtils.encodeUrlParameter(query);
|
return Uri.parse(SERVER_BASE_URL + "search/")
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter("text", query)
|
||||||
|
.build()
|
||||||
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
@@ -50,8 +50,10 @@ import java.net.URI;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to the configured MoasdaWiki server and downloads the wiki files.
|
* Connects to the configured MoasdaWiki server and downloads the wiki files.
|
||||||
@@ -287,7 +289,8 @@ public class SynchronizeWikiClient {
|
|||||||
|
|
||||||
// Antwort auswerten
|
// Antwort auswerten
|
||||||
ListModifiedFilesResponseXml response = parseXml(responseXml, ListModifiedFilesResponseXml.class);
|
ListModifiedFilesResponseXml response = parseXml(responseXml, ListModifiedFilesResponseXml.class);
|
||||||
int fileCount = response.fileList.size();
|
List<String> filePathsToDownload = determineFilesToDownload(response.fileList);
|
||||||
|
int fileCount = filePathsToDownload.size();
|
||||||
Log.d(TAG, "Downloading " + fileCount + " files from server");
|
Log.d(TAG, "Downloading " + fileCount + " files from server");
|
||||||
if (fileCount == 0) {
|
if (fileCount == 0) {
|
||||||
// no files to download, cancel process
|
// no files to download, cancel process
|
||||||
@@ -296,9 +299,9 @@ public class SynchronizeWikiClient {
|
|||||||
|
|
||||||
for (int i = 0; i < fileCount; i++) {
|
for (int i = 0; i < fileCount; i++) {
|
||||||
feedback.progress(i, fileCount);
|
feedback.progress(i, fileCount);
|
||||||
SingleFileXml serverFile = response.fileList.get(i);
|
String filePath = filePathsToDownload.get(i);
|
||||||
try {
|
try {
|
||||||
downloadFileFromServer(serverHostPort, serverSessionId, serverFile.filePath);
|
downloadFileFromServer(serverHostPort, serverSessionId, filePath);
|
||||||
}
|
}
|
||||||
catch (ServiceException e) {
|
catch (ServiceException e) {
|
||||||
Log.w(TAG, "Error reading file from server, ignoring it", e);
|
Log.w(TAG, "Error reading file from server, ignoring it", e);
|
||||||
@@ -321,6 +324,24 @@ public class SynchronizeWikiClient {
|
|||||||
return new SyncResult(true, true, false, fileCount);
|
return new SyncResult(true, true, false, fileCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
static List<String> determineFilesToDownload(@NonNull List<SingleFileXml> modifiedFiles) {
|
||||||
|
List<String> filePathsToDownload = new ArrayList<>();
|
||||||
|
for (SingleFileXml modifiedFile : modifiedFiles) {
|
||||||
|
String filePath = modifiedFile.filePath;
|
||||||
|
if (filePath != null && !filePathsToDownload.contains(filePath)) {
|
||||||
|
filePathsToDownload.add(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String appConfigFilePath = Settings.getConfigFileApp();
|
||||||
|
if (!filePathsToDownload.contains(appConfigFilePath)) {
|
||||||
|
filePathsToDownload.add(appConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePathsToDownload;
|
||||||
|
}
|
||||||
|
|
||||||
public static class SyncResult {
|
public static class SyncResult {
|
||||||
private final boolean sessionValid;
|
private final boolean sessionValid;
|
||||||
private final boolean sessionAuthorized;
|
private final boolean sessionAuthorized;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* MoasdaWiki App
|
* MoasdaWiki App
|
||||||
* Copyright (C) 2008 - 2025 Herbert Reiter (herbert@moasdawiki.net)
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License version 3 as published
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:contentAuthority="net.moasdawiki.app.provider"
|
android:contentAuthority="space.hackenslacker.moasdawiki.app.provider"
|
||||||
android:accountType="net.moasdawiki"
|
android:accountType="net.moasdawiki"
|
||||||
android:userVisible="false"
|
android:userVisible="false"
|
||||||
android:supportsUploading="false"
|
android:supportsUploading="false"
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* MoasdaWiki App
|
||||||
|
* Copyright (C) 2008 - 2026 Herbert Reiter (herbert@moasdawiki.net)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 3 as published
|
||||||
|
* by the Free Software Foundation (GPL-3.0-only).
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.moasdawiki.app;
|
||||||
|
|
||||||
|
import net.moasdawiki.service.sync.SingleFileXml;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SynchronizeWikiClientTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void determineFilesToDownloadAddsConfigFileAppWhenMissing() {
|
||||||
|
List<SingleFileXml> modifiedFiles = new ArrayList<>();
|
||||||
|
modifiedFiles.add(file("/wiki/Home-App.txt"));
|
||||||
|
|
||||||
|
List<String> result = SynchronizeWikiClient.determineFilesToDownload(modifiedFiles);
|
||||||
|
|
||||||
|
Assert.assertTrue(result.contains("/wiki/Home-App.txt"));
|
||||||
|
Assert.assertTrue(result.contains("/config-app.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void determineFilesToDownloadDoesNotDuplicateConfigFileApp() {
|
||||||
|
List<SingleFileXml> modifiedFiles = new ArrayList<>();
|
||||||
|
modifiedFiles.add(file("/config-app.txt"));
|
||||||
|
|
||||||
|
List<String> result = SynchronizeWikiClient.determineFilesToDownload(modifiedFiles);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (String filePath : result) {
|
||||||
|
if ("/config-app.txt".equals(filePath)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertEquals(1, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void determineFilesToDownloadRemovesDuplicatesAndNullValues() {
|
||||||
|
List<SingleFileXml> modifiedFiles = new ArrayList<>();
|
||||||
|
modifiedFiles.add(file("/wiki/PageA.txt"));
|
||||||
|
modifiedFiles.add(file("/wiki/PageA.txt"));
|
||||||
|
modifiedFiles.add(file(null));
|
||||||
|
|
||||||
|
List<String> result = SynchronizeWikiClient.determineFilesToDownload(modifiedFiles);
|
||||||
|
|
||||||
|
int pageACount = 0;
|
||||||
|
for (String filePath : result) {
|
||||||
|
if ("/wiki/PageA.txt".equals(filePath)) {
|
||||||
|
pageACount++;
|
||||||
|
}
|
||||||
|
Assert.assertNotNull(filePath);
|
||||||
|
}
|
||||||
|
Assert.assertEquals(1, pageACount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SingleFileXml file(String filePath) {
|
||||||
|
SingleFileXml xml = new SingleFileXml();
|
||||||
|
xml.filePath = filePath;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:8.12.2'
|
classpath 'com.android.tools.build:gradle:8.12.3'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- Bugfix: Zurück-Button hat App geschlossen
|
||||||
|
- Auf moasdawiki-server 3.9.7 aktualisieren
|
||||||
|
- Auf Java 17 aktualisieren
|
||||||
|
- Bibliotheks-Abhängigkeiten aktualisieren
|
||||||
|
- Copyright-Jahr aktualisieren
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- Bugfix: Use back gesture for browser back
|
||||||
|
- Upgrade to moasdawiki-server 3.9.7
|
||||||
|
- Upgrade to Java 17
|
||||||
|
- Upgrade library dependencies
|
||||||
|
- Update copyright year
|
||||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
|
distributionSha256Sum=72f44c9f8ebcb1af43838f45ee5c4aa9c5444898b3468ab3f4af7b6076c5bc3f
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -205,7 +205,7 @@ fi
|
|||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command:
|
# Collect all arguments for the java command:
|
||||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# and any embedded shellness will be escaped.
|
# and any embedded shellness will be escaped.
|
||||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# treated as '${Hostname}' itself on the command line.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-classpath "$CLASSPATH" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
Vendored
+2
-2
@@ -70,11 +70,11 @@ goto fail
|
|||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
Reference in New Issue
Block a user