mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-01-09 15:38:04 -05:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d54323fde0 | ||
|
|
c02be50242 | ||
|
|
a883ce0f43 | ||
|
|
ace353d71d | ||
|
|
18dbb24375 | ||
|
|
78daf54716 | ||
|
|
ee6541ba54 | ||
|
|
e4e9fe05e1 | ||
|
|
9d4035c94e | ||
|
|
293d38bd09 | ||
|
|
28be05600b | ||
|
|
03649820ce | ||
|
|
93515d2f88 | ||
|
|
d7dc70c0df | ||
|
|
ce0738782a | ||
|
|
df738b9c1d | ||
|
|
8bf0033d22 | ||
|
|
01e08e4928 | ||
|
|
90aee54a3c | ||
|
|
b7c42b5c8c |
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased - 162
|
||||
|
||||
- Fix list widget sometimes opening wrong card
|
||||
- Fix several bugs with shortcut handling
|
||||
- Fix About activity not using pure black title bar in OLED mode
|
||||
|
||||
## v2.41.4 - 161 (2026-01-04)
|
||||
|
||||
- Disable automatic barcode encoding detection for now (breaks too many cards)
|
||||
|
||||
@@ -69,7 +69,9 @@ class ListWidget : AppWidgetProvider() {
|
||||
if (hasCards) {
|
||||
// If we have cards, create the list
|
||||
views = RemoteViews(context.packageName, R.layout.list_widget)
|
||||
val templateIntent = Intent(context, LoyaltyCardViewActivity::class.java)
|
||||
val templateIntent = Intent(context, LoyaltyCardViewActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
|
||||
@@ -1532,7 +1532,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
DBHelper.setLoyaltyCardGroups(mDatabase, viewModel.getLoyaltyCardId(), selectedGroups);
|
||||
|
||||
ShortcutHelper.updateShortcuts(this, DBHelper.getLoyaltyCard(this, mDatabase, viewModel.getLoyaltyCardId()));
|
||||
ShortcutHelper.updateShortcuts(this);
|
||||
|
||||
if (viewModel.getDuplicateFromLoyaltyCardId()) {
|
||||
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
|
||||
|
||||
@@ -794,7 +794,7 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
invalidateOptionsMenu();
|
||||
|
||||
ShortcutHelper.updateShortcuts(this, loyaltyCard);
|
||||
ShortcutHelper.updateShortcuts(this);
|
||||
}
|
||||
|
||||
private void setStateBasedOnImageTypes() {
|
||||
@@ -896,7 +896,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(database, loyaltyCardId, 1);
|
||||
Toast.makeText(LoyaltyCardViewActivity.this, R.string.archived, Toast.LENGTH_LONG).show();
|
||||
|
||||
ShortcutHelper.removeShortcut(LoyaltyCardViewActivity.this, loyaltyCardId);
|
||||
new ListWidget().updateAll(LoyaltyCardViewActivity.this);
|
||||
|
||||
// Re-init loyaltyCard with new data from DB
|
||||
@@ -922,7 +921,6 @@ public class LoyaltyCardViewActivity extends CatimaAppCompatActivity implements
|
||||
|
||||
DBHelper.deleteLoyaltyCard(database, LoyaltyCardViewActivity.this, loyaltyCardId);
|
||||
|
||||
ShortcutHelper.removeShortcut(LoyaltyCardViewActivity.this, loyaltyCardId);
|
||||
new ListWidget().updateAll(LoyaltyCardViewActivity.this);
|
||||
|
||||
finish();
|
||||
|
||||
@@ -156,8 +156,6 @@ class MainActivity : CatimaAppCompatActivity(), CardAdapterListener {
|
||||
Log.d(TAG, "Deleting card: " + loyaltyCard.id)
|
||||
|
||||
DBHelper.deleteLoyaltyCard(mDatabase, this@MainActivity, loyaltyCard.id)
|
||||
|
||||
ShortcutHelper.removeShortcut(this@MainActivity, loyaltyCard.id)
|
||||
}
|
||||
val tab = groupsTabLayout.getTabAt(selectedTab)
|
||||
mGroup = tab?.tag
|
||||
@@ -177,7 +175,6 @@ class MainActivity : CatimaAppCompatActivity(), CardAdapterListener {
|
||||
for (loyaltyCard in mAdapter.getSelectedItems()) {
|
||||
Log.d(TAG, "Archiving card: " + loyaltyCard.id)
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id, 1)
|
||||
ShortcutHelper.removeShortcut(this@MainActivity, loyaltyCard.id)
|
||||
updateLoyaltyCardList(false)
|
||||
inputMode.finish()
|
||||
invalidateOptionsMenu()
|
||||
@@ -466,6 +463,7 @@ class MainActivity : CatimaAppCompatActivity(), CardAdapterListener {
|
||||
}
|
||||
|
||||
ListWidget().updateAll(mAdapter.mContext)
|
||||
ShortcutHelper.updateShortcuts(mAdapter.mContext)
|
||||
}
|
||||
|
||||
private fun processParseResultList(
|
||||
|
||||
@@ -2,31 +2,35 @@ package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
class ShortcutHelper {
|
||||
// Android documentation says that no more than 5 shortcuts
|
||||
// are supported. However, that may be too many, as not all
|
||||
// launcher will show all 5. Instead, the number is limited
|
||||
// to 3 here, so that the most recent shortcut has a good
|
||||
// chance of being shown.
|
||||
private static final int MAX_SHORTCUTS = 3;
|
||||
/**
|
||||
* This variable controls the maximum number of shortcuts available.
|
||||
* It is made public only to make testing easier and should not be
|
||||
* manually modified. We use -1 here as a default value to check if
|
||||
* the value has been set either manually by the test scenario or
|
||||
* automatically in the `updateShortcuts` function.
|
||||
* Its actual value will be set based on the maximum amount of shortcuts
|
||||
* declared by the launcher via `getMaxShortcutCountPerActivity`.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static int maxShortcuts = -1;
|
||||
|
||||
// https://developer.android.com/reference/android/graphics/drawable/AdaptiveIconDrawable.html
|
||||
private static final int ADAPTIVE_BITMAP_SCALE = 1;
|
||||
@@ -35,86 +39,42 @@ class ShortcutHelper {
|
||||
private static final int ADAPTIVE_BITMAP_IMAGE_SIZE = ADAPTIVE_BITMAP_VISIBLE_SIZE + 5 * ADAPTIVE_BITMAP_SCALE;
|
||||
|
||||
/**
|
||||
* Add a card to the app shortcuts, and maintain a list of the most
|
||||
* recently used cards. If there is already a shortcut for the card,
|
||||
* the card is marked as the most recently used card. If adding this
|
||||
* card exceeds the max number of shortcuts, then the least recently
|
||||
* used card shortcut is discarded.
|
||||
* Update the dynamic shortcut list with the most recently viewed cards
|
||||
* based on the lastUsed field. Archived cards are excluded from the shortcuts
|
||||
* list. The list keeps at most maxShortcuts number of elements.
|
||||
*/
|
||||
static void updateShortcuts(Context context, LoyaltyCard card) {
|
||||
if (card.archiveStatus == 1) {
|
||||
// Don't add archived card to menu
|
||||
return;
|
||||
static void updateShortcuts(Context context) {
|
||||
if (maxShortcuts == -1) {
|
||||
maxShortcuts = ShortcutManagerCompat.getMaxShortcutCountPerActivity(context);
|
||||
}
|
||||
|
||||
LinkedList<ShortcutInfoCompat> list = new LinkedList<>(ShortcutManagerCompat.getDynamicShortcuts(context));
|
||||
|
||||
SQLiteDatabase database = new DBHelper(context).getReadableDatabase();
|
||||
|
||||
String shortcutId = Integer.toString(card.id);
|
||||
|
||||
// Sort the shortcuts by rank, so working with the relative order will be easier.
|
||||
// This sorts so that the lowest rank is first.
|
||||
Collections.sort(list, Comparator.comparingInt(ShortcutInfoCompat::getRank));
|
||||
|
||||
Integer foundIndex = null;
|
||||
|
||||
for (int index = 0; index < list.size(); index++) {
|
||||
if (list.get(index).getId().equals(shortcutId)) {
|
||||
// Found the item already
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundIndex != null) {
|
||||
// If the item is already found, then the list needs to be
|
||||
// reordered, so that the selected item now has the lowest
|
||||
// rank, thus letting it survive longer.
|
||||
ShortcutInfoCompat found = list.remove(foundIndex.intValue());
|
||||
list.addFirst(found);
|
||||
} else {
|
||||
// The item is new to the list. We add it and trim the list later.
|
||||
ShortcutInfoCompat shortcut = createShortcutBuilder(context, card).build();
|
||||
list.addFirst(shortcut);
|
||||
}
|
||||
|
||||
LinkedList<ShortcutInfoCompat> finalList = new LinkedList<>();
|
||||
SQLiteDatabase database = new DBHelper(context).getReadableDatabase();
|
||||
Cursor loyaltyCardCursor = DBHelper.getLoyaltyCardCursor(
|
||||
database,
|
||||
"",
|
||||
null,
|
||||
DBHelper.LoyaltyCardOrder.LastUsed,
|
||||
DBHelper.LoyaltyCardOrderDirection.Ascending,
|
||||
DBHelper.LoyaltyCardArchiveFilter.Unarchived
|
||||
);
|
||||
|
||||
int rank = 0;
|
||||
|
||||
// The ranks are now updated; the order in the list is the rank.
|
||||
for (int index = 0; index < list.size(); index++) {
|
||||
ShortcutInfoCompat prevShortcut = list.get(index);
|
||||
while (rank < maxShortcuts && loyaltyCardCursor.moveToNext()) {
|
||||
int id = loyaltyCardCursor.getInt(loyaltyCardCursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
|
||||
LoyaltyCard loyaltyCard = DBHelper.getLoyaltyCard(context, database, id);
|
||||
|
||||
LoyaltyCard loyaltyCard = DBHelper.getLoyaltyCard(context, database, Integer.parseInt(prevShortcut.getId()));
|
||||
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
|
||||
.setRank(rank)
|
||||
.build();
|
||||
|
||||
// skip outdated cards that no longer exist
|
||||
if (loyaltyCard != null) {
|
||||
ShortcutInfoCompat updatedShortcut = createShortcutBuilder(context, loyaltyCard)
|
||||
.setRank(rank)
|
||||
.build();
|
||||
|
||||
finalList.addLast(updatedShortcut);
|
||||
rank++;
|
||||
|
||||
// trim the list
|
||||
if (rank >= MAX_SHORTCUTS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
finalList.addLast(updatedShortcut);
|
||||
rank++;
|
||||
}
|
||||
|
||||
ShortcutManagerCompat.setDynamicShortcuts(context, finalList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given card id from the app shortcuts, if such a
|
||||
* shortcut exists.
|
||||
*/
|
||||
static void removeShortcut(Context context, int cardId) {
|
||||
ShortcutManagerCompat.removeDynamicShortcuts(context, Collections.singletonList(Integer.toString(cardId)));
|
||||
}
|
||||
|
||||
static @NotNull
|
||||
Bitmap createAdaptiveBitmap(@NotNull Bitmap in, int paddingColor) {
|
||||
Bitmap ret = Bitmap.createBitmap(ADAPTIVE_BITMAP_SIZE, ADAPTIVE_BITMAP_SIZE, Bitmap.Config.ARGB_8888);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package protect.card_locker.compose
|
||||
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
@@ -8,18 +10,38 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import protect.card_locker.R
|
||||
import protect.card_locker.preferences.Settings
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CatimaTopAppBar(title: String, onBackPressedDispatcher: OnBackPressedDispatcher?) {
|
||||
// Use pure black in OLED theme
|
||||
val context = LocalContext.current
|
||||
val settings = Settings(context)
|
||||
val isDarkMode = when (settings.theme) {
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> false
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> true
|
||||
else -> isSystemInDarkTheme()
|
||||
}
|
||||
|
||||
val appBarColors = if (isDarkMode && settings.oledDark) {
|
||||
TopAppBarDefaults.topAppBarColors().copy(containerColor = Color.Black)
|
||||
} else {
|
||||
TopAppBarDefaults.topAppBarColors()
|
||||
}
|
||||
|
||||
TopAppBar(
|
||||
modifier = Modifier.testTag("topbar_catima"),
|
||||
title = { Text(text = title) },
|
||||
colors = appBarColors,
|
||||
navigationIcon = {
|
||||
if (onBackPressedDispatcher != null) {
|
||||
IconButton(onClick = { onBackPressedDispatcher.onBackPressed() }) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<string name="edit">Editar</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="ok">De acuerdo</string>
|
||||
<string name="ok">Aceptar</string>
|
||||
<string name="sendLabel">Enviar…</string>
|
||||
<string name="editCardTitle">Editar tarjeta</string>
|
||||
<string name="addCardTitle">Añadir tarjeta</string>
|
||||
@@ -134,7 +134,7 @@
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> seleccionadas</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> seleccionadas</item>
|
||||
</plurals>
|
||||
<string name="deleteTitle">Eliminar la tarjeta</string>
|
||||
<string name="deleteTitle">Eliminar tarjeta</string>
|
||||
<string name="deleteConfirmation">¿Quiere eliminar permanentemente esta tarjeta\?</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">¿Borrar esta tarjeta <xliff:g>%d</xliff:g> permanentemente\?</item>
|
||||
@@ -305,4 +305,7 @@
|
||||
<string name="copy_value">Copia valor</string>
|
||||
<string name="copied_to_clipboard">Copiado al portapapeles</string>
|
||||
<string name="nothing_to_copy">Ningún valor encontrado</string>
|
||||
<string name="barcodeEncoding">Codificación de barra de código</string>
|
||||
<string name="automatic">Automático</string>
|
||||
<string name="back">Atrás</string>
|
||||
</resources>
|
||||
|
||||
124
app/src/test/java/protect/card_locker/ShortcutHelperTest.java
Normal file
124
app/src/test/java/protect/card_locker/ShortcutHelperTest.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Color;
|
||||
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ShortcutHelperTest {
|
||||
private Activity mActivity;
|
||||
private SQLiteDatabase mDatabase;
|
||||
private int id1;
|
||||
private int id2;
|
||||
private int id3;
|
||||
private int id4;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mActivity = Robolectric.setupActivity(MainActivity.class);
|
||||
mDatabase = TestHelpers.getEmptyDb(mActivity).getWritableDatabase();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
id1 = (int) DBHelper.insertLoyaltyCard(mDatabase, "store1", "note1", null, null, new BigDecimal("0"), null, "cardId1", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), null, Color.BLACK, 0, now,0);
|
||||
id2 = (int) DBHelper.insertLoyaltyCard(mDatabase, "store2", "note2", null, null, new BigDecimal("0"), null, "cardId2", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), null, Color.BLACK, 0, now + 10,0);
|
||||
id3 = (int) DBHelper.insertLoyaltyCard(mDatabase, "store3", "note3", null, null, new BigDecimal("0"), null, "cardId3", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), null, Color.BLACK, 0, now + 20,0);
|
||||
id4 = (int) DBHelper.insertLoyaltyCard(mDatabase, "store4", "note4", null, null, new BigDecimal("0"), null, "cardId4", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), null, Color.BLACK, 0, now + 30,0);
|
||||
|
||||
ShortcutHelper.maxShortcuts = 3;
|
||||
}
|
||||
|
||||
private Integer[] getShortcutIds(Context context) {
|
||||
return ShortcutManagerCompat.getDynamicShortcuts(context)
|
||||
.stream()
|
||||
.sorted(Comparator.comparingInt(ShortcutInfoCompat::getRank))
|
||||
.map(shortcut -> Integer.parseInt(shortcut.getId()))
|
||||
.toArray(Integer[]::new);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onArchiveUnarchive() {
|
||||
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
|
||||
|
||||
Activity mainActivity = (Activity) activityController.get();
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
assertEquals(3, ShortcutManagerCompat.getDynamicShortcuts(mainActivity).stream().count());
|
||||
|
||||
Integer[] ids = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id4, id3, id2}, ids);
|
||||
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, id4, 1);
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
Integer[] idsAfterArchive = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id3, id2, id1}, idsAfterArchive);
|
||||
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, id4, 0);
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
Integer[] idsAfterUnarchive = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id4, id3, id2}, idsAfterUnarchive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAddRemoveFavorite() {
|
||||
ActivityController activityController = Robolectric.buildActivity(MainActivity.class).create();
|
||||
|
||||
Activity mainActivity = (Activity) activityController.get();
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
assertEquals(3, ShortcutManagerCompat.getDynamicShortcuts(mainActivity).stream().count());
|
||||
|
||||
Integer[] ids = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id4, id3, id2}, ids);
|
||||
|
||||
DBHelper.updateLoyaltyCardStarStatus(mDatabase, id1, 1);
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
Integer[] idsAfterFav = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id1, id4, id3}, idsAfterFav);
|
||||
|
||||
DBHelper.updateLoyaltyCardStarStatus(mDatabase, id1, 0);
|
||||
|
||||
activityController.pause();
|
||||
activityController.resume();
|
||||
|
||||
Integer[] idsAfterUnfav = getShortcutIds(mainActivity);
|
||||
|
||||
assertArrayEquals(new Integer[] {id4, id3, id2}, idsAfterUnfav);
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,4 @@
|
||||
- Einstellung für die Spaltenanzahl funktioniert nun auch in der Kartenansicht für Gruppen
|
||||
- Unterstützung für Designfarben entfernt
|
||||
- Maximale Fotogröße reduziert, um Speicherplatz zu sparen (gilt nur für neu hinzugefügte Fotos)
|
||||
- AboutActivity von Android XML zu Jetpack Compose migriert
|
||||
- About Activity von Android XML zu Jetpack Compose migriert
|
||||
|
||||
3
fastlane/metadata/android/en-US/changelogs/162.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/162.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Fix list widget sometimes opening wrong card
|
||||
- Fix several bugs with shortcut handling
|
||||
- Fix About activity not using pure black title bar in OLED mode
|
||||
2
fastlane/metadata/android/pl-PL/changelogs/151.txt
Normal file
2
fastlane/metadata/android/pl-PL/changelogs/151.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Nowy projekt logo Catima
|
||||
- Aktualizacja tłumaczeń
|
||||
3
fastlane/metadata/android/pl-PL/changelogs/152.txt
Normal file
3
fastlane/metadata/android/pl-PL/changelogs/152.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Dodanie wsparcia dla plików .pkpasses
|
||||
- Usunięcie importera Stocard (Stocard już nie istnieje)
|
||||
- Tymczasowe wyłączenie widżetów dla Androida poniżej 12L (obejście problemu awarii)
|
||||
Reference in New Issue
Block a user