Compare commits

...

12 Commits

Author SHA1 Message Date
Philipp Crocoll
a00267a0ac Manifest for 1.14-pre3 2025-08-19 18:04:45 +02:00
Philipp Crocoll
7fccb6cb16 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2025-08-19 18:04:01 +02:00
PhilippC
319f5d3113 Merge pull request #2983 from PhilippC/2893-bug-onedrive-sync-integration-no-longer-working-after-112-r5
attempt to fix app folder issue by creating it by an upload
2025-08-19 18:01:18 +02:00
Philipp Crocoll
b7276d1364 remove no-longer-sensible comment 2025-08-19 18:00:38 +02:00
Philipp Crocoll
58429ce0c4 attempt to fix app folder issue by creating it by an upload 2025-08-19 17:40:22 +02:00
Philipp Crocoll
72a72975e0 stability improvements 2025-08-19 12:25:38 +02:00
Philipp Crocoll
57be7af031 extend changelog for 1.14 2025-08-19 12:19:06 +02:00
Philipp Crocoll
5004a69bff modify release workflow to generate files as it was before on .net8 2025-08-19 11:19:52 +02:00
Philipp Crocoll
9628f2a1b8 manifest for 1.14-pre2 2025-08-12 17:36:03 +02:00
Philipp Crocoll
4cfdcb0f95 fix display issues with edge-to-edge when choosing file location; make file chooser look more modern 2025-08-12 17:23:13 +02:00
Philipp Crocoll
93d1eb9141 revert changes for https://github.com/PhilippC/keepass2android/issues/1617 because GnuTLS is currently not available for Android through FluentFTP 2025-08-12 14:43:37 +02:00
Philipp Crocoll
96f5953ed1 fix built-in keyboard padding on Android SDK 35 2025-08-12 14:04:29 +02:00
44 changed files with 364 additions and 184 deletions

View File

@@ -136,7 +136,23 @@ jobs:
- name: List apks
run: find . -type f -name "*.apk"
shell: bash
- name: Rename apks
# after updating to .net9, the naming scheme of the output apks has changed. rename them to the old scheme
# for consistancy with previous releases
run: |
for apk in src/keepass2android-app/bin/Release/net9.0-android/android-*/publish/*-Signed.apk; do
[ -e "$apk" ] || continue # if glob above doesn't return anything, the loop is still executed once
arch=$(basename "$(dirname "$(dirname "$apk")")") # e.g. "android-arm64"
base=$(basename "$apk" .apk) # e.g. "keepass2android.keepass2android_nonet-Signed"
mv "$apk" "$(dirname "$apk")/${base}-${arch#android-}.apk"
done
shell: bash
- name: List apks
run: find . -type f -name "*.apk"
shell: bash
- name: Upload APK to GitHub Release
uses: softprops/action-gh-release@v2
with:

View File

@@ -8,7 +8,6 @@ using Android.Content;
using Android.OS;
using FluentFTP;
using FluentFTP.Exceptions;
using FluentFTP.GnuTLS;
using KeePass.Util;
using KeePassLib;
using KeePassLib.Serialization;
@@ -141,7 +140,6 @@ namespace keepass2android.Io
var settings = ConnectionSettings.FromIoc(ioc);
FtpClient client = new FtpClient();
client.Config.CustomStream = typeof(GnuTlsStream);
client.Config.RetryAttempts = 3;
if ((settings.Username.Length > 0) || (settings.Password.Length > 0))
client.Credentials = new NetworkCredential(settings.Username, settings.Password);

View File

@@ -1125,9 +1125,57 @@ namespace keepass2android.Io
}
}
public static async Task<DriveItem> GetOrCreateAppRootAsync(GraphServiceClient client, string dummyFileName = "welcome_at_kp2a.txt")
{
private async Task<List<FileDescription>> ListShares(OneDrive2ItemLocation<OneDrive2PrefixContainerType> parentPath, GraphServiceClient client)
try
{
return await client.RequestAdapter.SendAsync(
new Microsoft.Graph.Drives.Item.Items.Item.DriveItemItemRequestBuilder(
new Dictionary<string, object> {
{ "drive%2Did", "me" },
{ "driveItem%2Did", "special/approot" }
},
client.RequestAdapter
).ToGetRequestInformation(),
static (p) => DriveItem.CreateFromDiscriminatorValue(p)
);
}
catch (Microsoft.Kiota.Abstractions.ApiException ex) when (ex.ResponseStatusCode == 404)
{
// App folder doesnt exist yet → create it by uploading a dummy file
using var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("init"));
var uploadRequest = new RequestInformation
{
HttpMethod = Method.PUT,
UrlTemplate = "{+baseurl}/me/drive/special/approot:/{filename}:/content",
PathParameters = new Dictionary<string, object>
{
{ "baseurl", client.RequestAdapter.BaseUrl },
{ "filename", dummyFileName }
},
Content = stream
};
var uploadedItem = await client.RequestAdapter.SendAsync<DriveItem>(
uploadRequest,
DriveItem.CreateFromDiscriminatorValue
);
var parentId = uploadedItem.ParentReference.Id;
var parentItemRequest = new DriveItemRequestBuilder(
$"{client.RequestAdapter.BaseUrl}/me/drive/items/{parentId}",
client.RequestAdapter
);
return await parentItemRequest.GetAsync();
}
}
protected virtual async Task<List<FileDescription>> ListShares(OneDrive2ItemLocation<OneDrive2PrefixContainerType> parentPath, GraphServiceClient client)
{
List<FileDescription> result = [];
@@ -1345,6 +1393,8 @@ namespace keepass2android.Io
}
}
protected override async Task<string?> GetSpecialFolder(
OneDrive2ItemLocation<OneDrive2AppFolderPrefixContainer> itemLocation, GraphServiceClient client)
@@ -1363,7 +1413,7 @@ namespace keepass2android.Io
Console.WriteLine(e);
throw;
}
}
return _specialFolderIdByDriveId[itemLocation.DriveId];
@@ -1378,8 +1428,55 @@ namespace keepass2android.Io
{
return drive.Name ?? MyOneDriveDisplayName;
}
public static async Task GetOrCreateAppRootAsync(GraphServiceClient client, string dummyFileName = "welcome_at_kp2a_app_folder.txt")
{
try
{
await client.RequestAdapter.SendAsync(
new Microsoft.Graph.Drives.Item.Items.Item.DriveItemItemRequestBuilder(
new Dictionary<string, object> {
{ "drive%2Did", "me" },
{ "driveItem%2Did", "special/approot" }
},
client.RequestAdapter
).ToGetRequestInformation(),
static (p) => DriveItem.CreateFromDiscriminatorValue(p)
);
//if this is successful, approot seems to exist
}
catch (Microsoft.Kiota.Abstractions.ApiException ex) when (ex.ResponseStatusCode == 404)
{
// App folder doesnt exist yet → create it by uploading a dummy file
using var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("init"));
var uploadRequest = new RequestInformation
{
HttpMethod = Method.PUT,
UrlTemplate = "{+baseurl}/me/drive/special/approot:/{filename}:/content",
PathParameters = new Dictionary<string, object>
{
{ "baseurl", client.RequestAdapter.BaseUrl },
{ "filename", dummyFileName }
},
Content = stream
};
await client.RequestAdapter.SendAsync<DriveItem>(
uploadRequest,
DriveItem.CreateFromDiscriminatorValue
);
}
}
protected override async Task<List<FileDescription>> ListShares(OneDrive2ItemLocation<OneDrive2AppFolderPrefixContainer> parentPath, GraphServiceClient client)
{
await GetOrCreateAppRootAsync(client);
return await base.ListShares(parentPath, client);
}
public override bool CanListShares { get { return false; } }
protected override string MyOneDriveDisplayName => "Keepass2Android App Folder";
}

View File

@@ -10,19 +10,18 @@
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentFTP" Version="52.1.0" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="FluentFTP.GnuTLS" Version="1.0.37" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="MegaApiClient" Version="1.10.4" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="Microsoft.Graph" Version="5.68.0" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="Microsoft.Identity.Client" Version="4.67.1" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="SMBLibrary" Version="1.5.4" Condition="'$(Flavor)'!='NoNet'"/>
<PackageReference Include="FluentFTP" Version="52.1.0" Condition="'$(Flavor)'!='NoNet'" />
<PackageReference Include="MegaApiClient" Version="1.10.4" Condition="'$(Flavor)'!='NoNet'" />
<PackageReference Include="Microsoft.Graph" Version="5.68.0" Condition="'$(Flavor)'!='NoNet'" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.67.1" Condition="'$(Flavor)'!='NoNet'" />
<PackageReference Include="SMBLibrary" Version="1.5.4" Condition="'$(Flavor)'!='NoNet'" />
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.8.0" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.13.1.5" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.11.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AndroidFileChooserBinding\AndroidFileChooserBinding.csproj" />
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj" Condition="'$(Flavor)'!='NoNet'" />
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj" Condition="'$(Flavor)'!='NoNet'" />
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj" />
<ProjectReference Include="..\KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj" />
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj" />
@@ -30,7 +29,7 @@
<ItemGroup>
</ItemGroup>
<ItemGroup Condition="'$(Flavor)'=='NoNet'">
<ItemGroup Condition="'$(Flavor)'=='NoNet'">
<None Remove="Io/OneDrive2FileStorage.cs" />
<Compile Remove="Io/OneDrive2FileStorage.cs" />
<Content Remove="Io/OneDrive2FileStorage.cs" />

View File

@@ -12,20 +12,21 @@ namespace KeePass.Util
public static string GetErrorMessage(Exception e)
{
string errorMessage = e.Message;
if (e is Java.Lang.Exception javaException)
try
{
try
string errorMessage = e.Message;
if (e is Java.Lang.Exception javaException)
{
errorMessage = javaException.LocalizedMessage ?? javaException.Message ?? errorMessage;
}
finally
{
}
return errorMessage;
}
catch
{
return "";
}
return errorMessage;
}
}

View File

@@ -6,8 +6,8 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 33
compileSdk 34
targetSdkVersion 35
compileSdk 35
}
buildTypes {
release {

View File

@@ -1,2 +1,3 @@
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.jetifier.ignorelist = jsch-2.27.2.jar

View File

@@ -3,12 +3,12 @@ apply plugin: 'com.android.application'
android {
namespace "com.crocoapps.javafilestoragetest2"
compileSdkVersion 33
compileSdkVersion 35
defaultConfig {
applicationId "com.crocoapps.javafilestoragetest2"
minSdkVersion 21
targetSdkVersion 33
targetSdkVersion 35
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -35,6 +35,7 @@ dependencies {
implementation project(':android-filechooser')
implementation project(':JavaFileStorage')
implementation "androidx.annotation:annotation:1.5.0"
implementation "com.google.android.material:material:1.12.0"
}
configurations {

View File

@@ -547,8 +547,8 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext);
//storageToTest = new GoogleDriveAppDataFileStorage();
storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
storageToTest = new GoogleDriveAppDataFileStorage();
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
@Override
public boolean onValidationError(String error) {
return false;
@@ -558,7 +558,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
public boolean alwaysFailOnValidationError() {
return false;
}
}, 64*1024);
}, 64*1024);*/
//storageToTest = new DropboxV2Storage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
//storageToTest = new DropboxFileStorage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);

View File

@@ -19,9 +19,12 @@ package keepass2android.softkeyboard;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.InflateException;
import android.view.View;
import android.view.WindowInsets;
import java.lang.ref.SoftReference;
import java.util.Arrays;
@@ -529,6 +532,28 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
}
mInputView.setOnKeyboardActionListener(mInputMethodService);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mInputView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
// Untere Systembar-Höhe holen
int insetBottom = insets.getSystemWindowInsetBottom();
// Padding nur unten anpassen
v.setPadding(
v.getPaddingLeft(),
v.getPaddingTop(),
v.getPaddingRight(),
insetBottom
);
// Insets normal weiterreichen
return insets;
}
});
}
mLayoutId = newLayout;
}
mInputMethodService.mHandler.post(new Runnable() {

View File

@@ -4,11 +4,11 @@ android {
namespace 'group.pals.android.lib.ui.filechooser'
compileSdkVersion 33
compileSdkVersion 35
defaultConfig {
minSdkVersion 16
targetSdkVersion 33
targetSdkVersion 35
}
buildTypes {
@@ -30,4 +30,5 @@ android {
dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "com.google.android.material:material:1.12.0"
}

View File

@@ -20,6 +20,8 @@ import android.content.Context;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import androidx.core.view.WindowCompat;
import androidx.fragment.app.FragmentActivity;
import android.util.Log;
import android.view.KeyEvent;
@@ -242,6 +244,7 @@ public class FileChooserActivity extends FragmentActivity {
R.style.Afc_Theme_Dark));
super.onCreate(savedInstanceState);
setContentView(R.layout.afc_activity_filechooser);
Ui.adjustDialogSizeForLargeScreen(getWindow());

View File

@@ -49,6 +49,10 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.CursorLoader;
@@ -324,6 +328,19 @@ public class FragmentFiles extends Fragment implements
* INIT CONTROLS
*/
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, windowInsets) -> {
Insets systemBarsInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.navigationBars() | WindowInsetsCompat.Type.ime());
v.setPadding(
systemBarsInsets.left,
systemBarsInsets.top,
systemBarsInsets.right,
systemBarsInsets.bottom
);
return WindowInsetsCompat.CONSUMED;
});
return rootView;
}// onCreateView()

View File

@@ -8,8 +8,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_ic_button_ok_saveas_light_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/afc_ic_button_ok_saveas_light_focused" android:state_focused="true"/>
<item android:drawable="@drawable/afc_ic_button_ok_saveas_light"/>
<item android:drawable="@drawable/save_icon"/>
</selector>

View File

@@ -8,8 +8,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_ic_button_ok_saveas_dark_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/afc_ic_button_ok_saveas_dark_focused" android:state_focused="true"/>
<item android:drawable="@drawable/afc_ic_button_ok_saveas_dark"/>
<item android:drawable="@drawable/save_icon"/>
</selector>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Disabled -->
<item android:state_enabled="false"
android:drawable="@drawable/baseline_chevron_left_24_alpha30" />
<!-- Default -->
<item android:drawable="@drawable/baseline_chevron_left_24" />
</selector>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_main_button_navi_left_pressed_dark" android:state_pressed="true"/> <!-- pressed -->
<item android:drawable="@drawable/afc_main_button_navi_left_disabled_dark" android:state_enabled="false"/> <!-- enabled -->
<item android:drawable="@drawable/afc_main_button_navi_left_dark"/> <!-- default -->
</selector>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_main_button_navi_left_pressed_light" android:state_pressed="true"/> <!-- pressed -->
<item android:drawable="@drawable/afc_main_button_navi_left_disabled_light" android:state_enabled="false"/> <!-- enabled -->
<item android:drawable="@drawable/afc_main_button_navi_left_light"/> <!-- default -->
</selector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Disabled -->
<item android:state_enabled="false"
android:drawable="@drawable/baseline_chevron_right_24_alpha30" />
<!-- Default -->
<item android:drawable="@drawable/baseline_chevron_right_24" />
</selector>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_main_button_navi_right_pressed_dark" android:state_pressed="true"/> <!-- pressed -->
<item android:drawable="@drawable/afc_main_button_navi_right_disabled_dark" android:state_enabled="false"/> <!-- enabled -->
<item android:drawable="@drawable/afc_main_button_navi_right_dark"/> <!-- default -->
</selector>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/afc_main_button_navi_right_pressed_light" android:state_pressed="true"/> <!-- pressed -->
<item android:drawable="@drawable/afc_main_button_navi_right_disabled_light" android:state_enabled="false"/> <!-- enabled -->
<item android:drawable="@drawable/afc_main_button_navi_right_light"/> <!-- default -->
</selector>

View File

@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp" android:tint="?attr/colorOnSurface"
android:viewportHeight="24" android:viewportWidth="24"
android:width="36dp">
<path android:fillColor="@android:color/white" android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
</vector>

View File

@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp" android:tint="?attr/colorOnSurface"
android:viewportHeight="24" android:viewportWidth="24"
android:width="36dp">
<path android:fillColor="@android:color/white" android:fillAlpha="0.3" android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
</vector>

View File

@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp" android:tint="?attr/colorOnSurface"
android:viewportHeight="24" android:viewportWidth="24"
android:width="36dp">
<path android:fillColor="@android:color/white" android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

View File

@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp" android:tint="?attr/colorOnSurface"
android:viewportHeight="24" android:viewportWidth="24"
android:width="36dp">
<path android:fillColor="@android:color/white" android:fillAlpha="0.3" android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

View File

@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="36dp" android:tint="?attr/colorOnSurface"
android:viewportHeight="24" android:viewportWidth="24"
android:width="36dp">
<path android:fillColor="@android:color/white" android:pathData="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/>
</vector>

View File

@@ -42,9 +42,9 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginBottom="@dimen/afc_2dp"
android:layout_marginTop="@dimen/afc_5dp"
android:layout_marginBottom="@dimen/afc_5dp"
android:layout_marginRight="@dimen/afc_5dp"
android:layout_marginTop="@dimen/afc_2dp"
android:layout_weight="0.1"
android:orientation="vertical" >
@@ -55,8 +55,8 @@
android:ellipsize="middle"
android:maxLines="3"
android:singleLine="false"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textIsSelectable="false" />
android:textIsSelectable="false"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"/>
<TextView
android:id="@+id/afc_textview_file_info"
@@ -66,7 +66,8 @@
android:ellipsize="end"
android:gravity="right"
android:singleLine="true"
android:textIsSelectable="false" />
android:textIsSelectable="false"
android:textAppearance="@style/TextAppearance.Material3.BodySmall" />
</LinearLayout>
<CheckBox

View File

@@ -8,7 +8,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/afc_viewgroup_header"
@@ -47,21 +47,14 @@
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:showDividers="middle" />
/>
</HorizontalScrollView>
<View
android:id="@+id/afc_header_view_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/afc_viewgroup_button_locations_bottom_divider_height"
android:layout_below="@id/afc_view_locations_container"
android:background="@color/afc_border_line_dark" />
<TextView
android:id="@+id/afc_textview_full_dir_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/afc_header_view_divider"
android:layout_below="@id/afc_view_locations_container"
android:layout_centerHorizontal="true"
android:ellipsize="start"
android:gravity="center"
@@ -122,10 +115,6 @@
android:orientation="vertical"
android:visibility="gone" >
<View
android:id="@+id/afc_footer_view_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/afc_viewgroup_button_locations_bottom_divider_height" />
<LinearLayout
android:id="@+id/afc_viewgroup_footer"

View File

@@ -9,6 +9,8 @@
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"
android:dividerHeight="0dp"
android:fastScrollEnabled="true" >
</ListView>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Afc.BaseTheme.Dark" parent="Theme.Material3.Dark.NoActionBar">
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="Afc.BaseThemeHelper.Dark" parent="Theme.Material3.Dark.NoActionBar">
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="Afc.BaseThemeHelper.Light" parent="Theme.Material3.Light.NoActionBar">
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="Afc.BaseTheme.Light" parent="Theme.Material3.Light.NoActionBar">
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>

View File

@@ -1,63 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AOSP_DialogWindowTitle">
<style name="AOSP_DialogWindowTitle">
<item name="android:maxLines">1</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:textAppearance">@android:style/TextAppearance.DialogWindowTitle</item>
</style>
<style name="afc_main_button_navi">
<style name="afc_main_button_navi">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:adjustViewBounds">true</item>
<item name="android:scaleType">center</item>
<item name="android:layout_marginLeft">@dimen/afc_5dp</item>
<item name="android:layout_marginTop">@dimen/afc_5dp</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:minHeight">@dimen/afc_button_navigators_min_height</item>
</style>
<style name="afc_main_button_navi_left" parent="@style/afc_main_button_navi">
<item name="android:src">?attr/afc_selector_main_button_navi_left</item>
</style>
</style>
<style name="afc_main_button_navi_right" parent="@style/afc_main_button_navi">
<item name="android:src">?attr/afc_selector_main_button_navi_right</item>
<item name="android:layout_marginRight">@dimen/afc_5dp</item>
</style>
<style name="afc_action_navi">
<style name="afc_action_navi">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:adjustViewBounds">true</item>
<item name="android:scaleType">center</item>
<item name="android:background">?attr/afc_selector_image_button</item>
<item name="android:background">?attr/afc_selector_image_button</item>
<item name="android:layout_margin">@dimen/afc_2dp</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_gravity">center</item>
</style>
<style name="afc_action_navi_left" parent="@style/afc_action_navi">
<item name="android:src">?attr/afc_selector_action_navi_left_foreground</item>
</style>
</style>
<style name="afc_action_navi_right" parent="@style/afc_action_navi">
<item name="android:src">?attr/afc_selector_action_navi_right_foreground</item>
</style>
</style>
<style name="afc_base_button_location" parent="@android:style/Widget.TextView"></style>
<style name="afc_button_location" parent="@style/afc_base_button_location">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:background">?attr/afc_selector_button_location</item>
<item name="android:layout_margin">@dimen/afc_5dp</item>
<item name="android:ellipsize">end</item>
@@ -65,11 +57,11 @@
<item name="android:minWidth">@dimen/afc_button_location_min_width</item>
<item name="android:padding">@dimen/afc_5dp</item>
<item name="android:singleLine">true</item>
<item name="android:gravity">center</item>
<item name="android:gravity">center</item>
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
</style>
<style name="afc_widget_search_view_button_search">
<style name="afc_widget_search_view_button_search">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">?attr/afc_selector_image_button</item>
@@ -80,10 +72,10 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@null</item>
<item name="android:src">?attr/afc_ic_widget_search_view_action_clear</item>
<item name="android:src">?attr/afc_ic_widget_search_view_action_clear</item>
</style>
<style name="afc_button_sort" parent="@android:style/Widget.ImageButton">
<style name="afc_button_sort" parent="@android:style/Widget.ImageButton">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center</item>
@@ -91,11 +83,11 @@
<item name="android:padding">@dimen/afc_5dp</item>
</style>
<style name="afc_home_button_navigators" parent="@android:style/Widget.TextView">
<style name="afc_home_button_navigators" parent="@android:style/Widget.TextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:background">?attr/afc_selector_button_location</item>
<item name="android:background">?attr/afc_selector_button_location</item>
<item name="android:layout_margin">@dimen/afc_2dp</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>

View File

@@ -16,7 +16,7 @@
- Actual themes which extend BaseThemeHelpers: contain customizations that are the same for all API levels.
-->
<style name="Afc.BaseTheme.Dark" parent="@android:style/Theme"></style>
<style name="Afc.BaseTheme.Dark" parent="Theme.Material3.Dark.NoActionBar"></style>
<style name="Afc.BaseThemeHelper.Dark" parent="@style/Afc.BaseTheme.Dark">
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
@@ -39,15 +39,13 @@
<item name="afc_ic_widget_search_view_action_clear">@drawable/afc_ic_action_clear_dark</item>
</style>
<style name="Afc.BaseTheme.Dialog.Dark" parent="@android:style/Theme" />
<style name="Afc.BaseTheme.Dialog.Dark" parent="Theme.Material3.Dark.NoActionBar" />
<style name="Afc.BaseThemeHelper.Dialog.Dark" parent="@style/Afc.BaseTheme.Dialog.Dark">
<!-- AOSP -->
<item name="android:windowFrame">@null</item>
<item name="android:windowTitleStyle">@style/AOSP_DialogWindowTitle</item>
<item name="android:windowBackground">@drawable/aosp_dialog_full_holo_dark</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
@@ -81,10 +79,6 @@
<style name="Afc.Theme.Dark" parent="@style/Afc.BaseThemeHelper.Dark">
<!-- AOSP -->
<item name="android:windowBackground">@drawable/aosp_background_holo_dark</item>
<!-- android-filechooser -->
<item name="afc_theme_dialog">@style/Afc.Theme.Dialog.Dark</item>
@@ -93,9 +87,9 @@
<item name="afc_badge_file_provider_localfile">@drawable/afc_badge_file_provider_localfile_light</item>
<item name="afc_selector_image_button">@drawable/afc_selector_image_button_dark</item>
<item name="afc_selector_button_location">@drawable/afc_selector_button_location_dark</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left_dark</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right_dark</item>
<item name="afc_selector_button_ok_saveas">@drawable/afc_selector_button_ok_saveas_dark</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right</item>
<item name="afc_selector_button_ok_saveas">@drawable/save_icon</item>
<item name="afc_selector_action_navi_left_foreground">@drawable/afc_selector_action_navi_left_dark_foreground</item>
<item name="afc_selector_action_navi_right_foreground">@drawable/afc_selector_action_navi_right_dark_foreground</item>
<item name="afc_color_listview_cache_hint">@color/afc_listview_cache_hint_dark</item>
@@ -109,8 +103,8 @@
<item name="afc_badge_file_provider_localfile">@drawable/afc_badge_file_provider_localfile_light</item>
<item name="afc_selector_image_button">@drawable/afc_selector_image_button_dark</item>
<item name="afc_selector_button_location">@drawable/afc_selector_button_location_dark</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left_dark</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right_dark</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right</item>
<item name="afc_selector_button_ok_saveas">@drawable/afc_selector_button_ok_saveas_dark</item>
<item name="afc_selector_action_navi_left_foreground">@drawable/afc_selector_action_navi_left_dark_foreground</item>
<item name="afc_selector_action_navi_right_foreground">@drawable/afc_selector_action_navi_right_dark_foreground</item>

View File

@@ -16,9 +16,11 @@
- Actual themes which extend BaseThemeHelpers: contain customizations that are the same for all API levels.
-->
<style name="Afc.BaseTheme.Light" parent="@android:style/Theme.Light"></style>
<style name="Afc.BaseTheme.Light" parent="Theme.Material3.Light.NoActionBar">
<style name="Afc.BaseThemeHelper.Light" parent="@style/Afc.BaseTheme.Light">
</style>
<style name="Afc.BaseThemeHelper.Light" parent="Theme.Material3.Light.NoActionBar">
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview</item>
@@ -46,7 +48,6 @@
<item name="android:windowFrame">@null</item>
<item name="android:windowTitleStyle">@style/AOSP_DialogWindowTitle</item>
<item name="android:windowBackground">@drawable/aosp_dialog_full_holo_light</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
@@ -78,11 +79,6 @@
</style>
<style name="Afc.Theme.Light" parent="@style/Afc.BaseThemeHelper.Light">
<!-- AOSP -->
<item name="android:windowBackground">@drawable/aosp_background_holo_light</item>
<!-- android-filechooser -->
<item name="afc_theme_dialog">@style/Afc.Theme.Dialog.Light</item>
@@ -92,8 +88,8 @@
<item name="afc_badge_file_provider_localfile">@drawable/afc_badge_file_provider_localfile_dark</item>
<item name="afc_selector_image_button">@drawable/afc_selector_image_button_light</item>
<item name="afc_selector_button_location">@drawable/afc_selector_button_location_light</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left_light</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right_light</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right</item>
<item name="afc_selector_button_ok_saveas">@drawable/afc_selector_button_ok_saveas_light</item>
<item name="afc_selector_action_navi_left_foreground">@drawable/afc_selector_action_navi_left_light_foreground</item>
<item name="afc_selector_action_navi_right_foreground">@drawable/afc_selector_action_navi_right_light_foreground</item>
@@ -120,8 +116,8 @@
<item name="afc_badge_file_provider_localfile">@drawable/afc_badge_file_provider_localfile_dark</item>
<item name="afc_selector_image_button">@drawable/afc_selector_image_button_light</item>
<item name="afc_selector_button_location">@drawable/afc_selector_button_location_light</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left_light</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right_light</item>
<item name="afc_selector_main_button_navi_left">@drawable/afc_selector_main_button_navi_left</item>
<item name="afc_selector_main_button_navi_right">@drawable/afc_selector_main_button_navi_right</item>
<item name="afc_selector_button_ok_saveas">@drawable/afc_selector_button_ok_saveas_light</item>
<item name="afc_selector_action_navi_left_foreground">@drawable/afc_selector_action_navi_left_light_foreground</item>
<item name="afc_selector_action_navi_right_foreground">@drawable/afc_selector_action_navi_right_light_foreground</item>

View File

@@ -31,9 +31,15 @@ namespace keepass2android
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
builder.SetTitle(ctx.GetString(Resource.String.ChangeLog_title));
List<string> changeLog = new List<string>{
#if !NoNet
BuildChangelogString(ctx, new List<int>{Resource.Array.ChangeLog_1_14_net}, "1.14"),
#endif
BuildChangelogString(ctx, new List<int>
{
Resource.Array.ChangeLog_1_14,
#if !NoNet
Resource.Array.ChangeLog_1_14_net
#endif
}, "1.14"),
BuildChangelogString(ctx, new List<int>{Resource.Array.ChangeLog_1_13}, "1.13"),

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="224"
android:versionName="1.14-pre1"
android:versionCode="236"
android:versionName="1.14-pre3"
package="keepass2android.keepass2android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="224"
android:versionName="1.14-pre1"
android:versionCode="236"
android:versionName="1.14-pre3"
package="keepass2android.keepass2android_nonet"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">

View File

@@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fitsSystemWindows="true"
android:id="@+id/root"
android:layout_margin="12dip">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

View File

@@ -732,7 +732,6 @@
<string-array name="ChangeLog_1_14_net">
<item>Vylepšení WebDav: Oprava chyby při zobrazování seznamu složek; podpora fragmentovaných nahrávání a transakcí</item>
<item>Přidána podpora pro Sambu/síťové sdílení Windows</item>
<item>Aktualizován FluentFTP a povolena podpora pro GnuTLS stream, podporující TLS 1.3 a řešící další problémy FTPS</item>
</string-array>
<string-array name="ChangeLog_1_13">
<item>Vylepšené hodnocení kvality hesel založené na nejčastěji používaných heslech.</item>

View File

@@ -732,7 +732,6 @@ Anbei einige Tipps, die bei der Diagnose des Problems helfen können:\n
<string-array name="ChangeLog_1_14_net">
<item>WebDav-Verbesserungen: Fehlerbehebung für die Ordnerauflistung; Unterstützung für chunked Uploads und Transaktionen</item>
<item>Unterstützung für Samba/Windows-Netzwerkfreigaben hinzugefügt</item>
<item>FluentFTP aktualisiert und Unterstützung für GnuTLS Stream aktiviert, TLS 1.3 wird unterstützt und andere FTPS Probleme gelöst</item>
</string-array>
<string-array name="ChangeLog_1_13">
<item>Verbesserte Einschätzung der Passwortqualität, indem die beliebtesten Passwörter berücksichtigt werden.</item>

View File

@@ -734,7 +734,6 @@
<string-array name="ChangeLog_1_14_net">
<item>Améliorations de WebDav : Correction d\'un bogue pour l\'énumération des dossiers ; prise en charge des téléchargements et des transactions par morceaux.</item>
<item>Ajout de la prise en charge des partages réseau Samba/Windows</item>
<item>Mise à jour de FluentFTP et la prise en charge du flux GnuTLS, supportant TLS 1.3 et résolvant d\'autres problèmes FTPS</item>
</string-array>
<string-array name="ChangeLog_1_13">
<item>Estimation de la qualité du mot de passe améliorée en tenant compte des mots de passe les plus populaires.</item>

View File

@@ -736,7 +736,6 @@
<string-array name="ChangeLog_1_14_net">
<item>Melhorias no WebDav: Correção de bug ao listar pastas; Suporte para uploads e transações em blocos</item>
<item>Adicionado suporte para compartilhamentos de rede Samba/Windows</item>
<item>Atualizado o FluentFTP e habilitado o suporte para o fluxo GnuTLS, suportando o TLS 1.3 e resolvendo outros problemas de FTPS</item>
</string-array>
<string-array name="ChangeLog_1_13">
<item>Estimativa aprimorada da qualidade da senha, considerando a maioria das senhas populares.</item>

View File

@@ -741,10 +741,14 @@
<string name="webdav_chunked_upload_size_title">Chunk size for WebDav upload</string>
<string name="webdav_chunked_upload_size_summary">Size of chunks when uploading to WebDav servers in bytes. Use 0 to disable chunked upload.</string>
<string-array name="ChangeLog_1_14">
<item>Update to .net 9 and Target SDK version 35. This comes with transparent status bar on Android 15 because edge-to-edge is now the default.</item>
<item>Minor UI improvements</item>
</string-array>
<string-array name="ChangeLog_1_14_net">
<item>WebDav improvements: Bug fix for listing folders; support for chunked uploads and transactions</item>
<item>Added support for Samba/Windows network shares</item>
<item>Updated FluentFTP and enabled support for GnuTLS stream, supporting TLS 1.3 and solving other FTPS issues</item>
<item>Updated JSch to support more modern algorithms in SFTP</item>
</string-array>

View File

@@ -131,7 +131,15 @@ namespace keepass2android.view
ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible;
ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible;
_db = App.Kp2a.FindDatabaseForElement(_entry);
_db = App.Kp2a.TryFindDatabaseForElement(_entry);
if (_db == null)
{
ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Gone;
_textView.TextFormatted = new SpannableString("(no data)");
_textviewDetails.Visibility = ViewStates.Gone;
_textgroupFullPath.Visibility = ViewStates.Gone;
return;
}
ImageView iv = (ImageView)ev.FindViewById(Resource.Id.icon);
bool isExpired = pw.Expires && pw.ExpiryTime < DateTime.Now;
@@ -209,11 +217,6 @@ namespace keepass2android.view
UpdateTotp();
}
public void ConvertView(PwEntry pw, int pos)

View File

@@ -15,14 +15,15 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Text;
using Android.Views;
using Android.Widget;
using keepass2android;
using KeePassLib;
using System;
using Object = Java.Lang.Object;
namespace keepass2android.view
@@ -64,7 +65,20 @@ namespace keepass2android.view
_label = (TextView) gv.FindViewById(Resource.Id.group_label);
_label.TextSize = size-8;
Database db = App.Kp2a.FindDatabaseForElement(pw);
Database db = App.Kp2a.TryFindDatabaseForElement(pw);
if (db == null)
{
gv.FindViewById(Resource.Id.group_icon_bkg).Visibility = ViewStates.Gone;
gv.FindViewById(Resource.Id.icon).Visibility = ViewStates.Gone;
gv.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible;
_textview.Text = "(no data)";
_label.Text = "";
return;
}
gv.FindViewById(Resource.Id.group_icon_bkg).Visibility = db.DrawableFactory.IsWhiteIconSet ? ViewStates.Visible : ViewStates.Gone;