mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2025-12-24 15:47:53 -05:00
Compare commits
721 Commits
v2.17.1
...
group_db_i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70cdb18c51 | ||
|
|
a74e17db10 | ||
|
|
96335d3ee8 | ||
|
|
fb3d945f51 | ||
|
|
843ffbb87e | ||
|
|
99e19321f0 | ||
|
|
4e5a90eb93 | ||
|
|
9745ea671e | ||
|
|
94a63d6e0c | ||
|
|
725ca3b9ca | ||
|
|
46a2164143 | ||
|
|
5304be6f54 | ||
|
|
8321e796f5 | ||
|
|
c1f82e90be | ||
|
|
758f265638 | ||
|
|
590020bb6f | ||
|
|
f18c2a2d0c | ||
|
|
3a17ee83e0 | ||
|
|
f36d4aebb6 | ||
|
|
71cb1cace4 | ||
|
|
1e4e035281 | ||
|
|
7da4eb6587 | ||
|
|
d454864fa7 | ||
|
|
f5e6d7be71 | ||
|
|
967a17242d | ||
|
|
6c5dd7a713 | ||
|
|
139b144cb3 | ||
|
|
5deacf7ecc | ||
|
|
6e49aea713 | ||
|
|
68257ce3ad | ||
|
|
149a1caeff | ||
|
|
07e5788cb2 | ||
|
|
c072e2e70d | ||
|
|
0701b9b3de | ||
|
|
f84242d97c | ||
|
|
79f35ed715 | ||
|
|
eff4f3f8df | ||
|
|
ee405f670d | ||
|
|
7dcb9b336d | ||
|
|
923e6dc062 | ||
|
|
2ea04e8715 | ||
|
|
f264941ae4 | ||
|
|
e6ef5c9bb2 | ||
|
|
024cc2d50e | ||
|
|
48b62f6aea | ||
|
|
ff07fe71cc | ||
|
|
402cf57c29 | ||
|
|
e19ac0d0c2 | ||
|
|
fc5d4a6435 | ||
|
|
50754a3430 | ||
|
|
0375f6dbe5 | ||
|
|
deb808ffb6 | ||
|
|
166c1e7bc6 | ||
|
|
bfa19d0166 | ||
|
|
f92805ec64 | ||
|
|
73e6e9f34a | ||
|
|
6a76681412 | ||
|
|
f05a5dde1e | ||
|
|
4a93ba3478 | ||
|
|
af43138ae9 | ||
|
|
dcd6e4b9a9 | ||
|
|
0ce2395605 | ||
|
|
89dbc9e9aa | ||
|
|
788a8f0efe | ||
|
|
d0c9ae2a4a | ||
|
|
c000a8129c | ||
|
|
bfb4fdb61c | ||
|
|
1929401d3e | ||
|
|
eef13a1a91 | ||
|
|
64f340d798 | ||
|
|
f12422fc07 | ||
|
|
d78315ef12 | ||
|
|
af8c3eeb54 | ||
|
|
16e4205028 | ||
|
|
399aa767d2 | ||
|
|
96c735cf80 | ||
|
|
50a8395ec6 | ||
|
|
c720ca1085 | ||
|
|
d82088f66a | ||
|
|
1fce3e17f6 | ||
|
|
569db96f81 | ||
|
|
b7cb1dffc1 | ||
|
|
e17fc66d35 | ||
|
|
8dac7ae9d1 | ||
|
|
28a0417fa8 | ||
|
|
58d4bd7f47 | ||
|
|
1779aef162 | ||
|
|
557ec68428 | ||
|
|
96a7c8ee36 | ||
|
|
3a9b92231e | ||
|
|
f1753ea943 | ||
|
|
36ab78ec6e | ||
|
|
8a3a782558 | ||
|
|
2c5606bf0a | ||
|
|
5eb36aad5b | ||
|
|
b028d32e2c | ||
|
|
dfefdda9f9 | ||
|
|
bc1cc68f27 | ||
|
|
386a5f75b0 | ||
|
|
d30a9fd1e5 | ||
|
|
0c8e5576b8 | ||
|
|
93e40c08aa | ||
|
|
24eb1e9627 | ||
|
|
19e6b8bea9 | ||
|
|
87f844943e | ||
|
|
718738ff78 | ||
|
|
d7bb019068 | ||
|
|
f925404ab7 | ||
|
|
38495546e0 | ||
|
|
36e7ea5b20 | ||
|
|
85d53ae3c7 | ||
|
|
e9b6b5682e | ||
|
|
0abc583d10 | ||
|
|
8c91d30b4c | ||
|
|
76e8715ab2 | ||
|
|
f5f2edca75 | ||
|
|
e648e22ecc | ||
|
|
02b020e9e5 | ||
|
|
e7dc3cd511 | ||
|
|
eb3ac53e46 | ||
|
|
dd683b4a8c | ||
|
|
e90ba5d2db | ||
|
|
07cff7eac4 | ||
|
|
3eea18fc82 | ||
|
|
5d3ceb6d49 | ||
|
|
3dc7a25d88 | ||
|
|
95e02d1646 | ||
|
|
81ecf8ba92 | ||
|
|
bf0e1a2e77 | ||
|
|
4d1c9244fd | ||
|
|
1f1e523100 | ||
|
|
cb32cf9e52 | ||
|
|
af812d8cda | ||
|
|
c8a7addc52 | ||
|
|
3e64d7c5ad | ||
|
|
277462a939 | ||
|
|
24623d5c58 | ||
|
|
4b25b7ad39 | ||
|
|
4016d5499b | ||
|
|
d8b96a8c5f | ||
|
|
614753303f | ||
|
|
50a344b97f | ||
|
|
2cd6da6ffc | ||
|
|
c03fba133f | ||
|
|
f3cba588f6 | ||
|
|
ad364ad0ac | ||
|
|
f4cff85d93 | ||
|
|
cbc86ff131 | ||
|
|
5f733474a9 | ||
|
|
89a13cecf5 | ||
|
|
fd2400eaf5 | ||
|
|
9598f2f4ff | ||
|
|
acca53787c | ||
|
|
060e360344 | ||
|
|
9ef014e05c | ||
|
|
4cb27d3bd5 | ||
|
|
95e21cc112 | ||
|
|
d5f915a290 | ||
|
|
42e89bb5cc | ||
|
|
048fb48300 | ||
|
|
b1c82dbae0 | ||
|
|
ea8c6f96f7 | ||
|
|
201ec78694 | ||
|
|
05a03455c1 | ||
|
|
63f4cbb8ca | ||
|
|
a444607476 | ||
|
|
89102ad0bf | ||
|
|
d2623b8690 | ||
|
|
80ddd48184 | ||
|
|
410a619a70 | ||
|
|
1771f42860 | ||
|
|
1e7af7ab4e | ||
|
|
f4c5af04e3 | ||
|
|
5bcd2cdc32 | ||
|
|
c69a5ae4d2 | ||
|
|
6bd750a60b | ||
|
|
8d77cc3565 | ||
|
|
7a99e0056d | ||
|
|
03e07bc48d | ||
|
|
460d6c2b71 | ||
|
|
9f946094db | ||
|
|
4e92f82176 | ||
|
|
7b905ac120 | ||
|
|
55c5ec929c | ||
|
|
5441231f03 | ||
|
|
1818d24bc0 | ||
|
|
ca88c070c3 | ||
|
|
1be387c4ec | ||
|
|
fa3a956d69 | ||
|
|
8fd244e3a3 | ||
|
|
a0e2fe11dd | ||
|
|
893f34e72a | ||
|
|
cf13a9fc60 | ||
|
|
c6e6d96313 | ||
|
|
20ed9cac88 | ||
|
|
ae6bd937a9 | ||
|
|
e4b69e5cc5 | ||
|
|
5b1062b8d1 | ||
|
|
e06009852e | ||
|
|
50268f6bd1 | ||
|
|
a85e28d46d | ||
|
|
78b6be911f | ||
|
|
bb80478650 | ||
|
|
e0c06cc480 | ||
|
|
b8a508649c | ||
|
|
a8ce37d936 | ||
|
|
43015abbad | ||
|
|
47c8dff52d | ||
|
|
436cf7a068 | ||
|
|
31cc3cd5d0 | ||
|
|
3c11c2ef1e | ||
|
|
fac70f0210 | ||
|
|
6e99a29312 | ||
|
|
5b67ecf157 | ||
|
|
312470cf20 | ||
|
|
4371f46ff8 | ||
|
|
5468415b04 | ||
|
|
6a68ad5d19 | ||
|
|
7576505044 | ||
|
|
b34a43902a | ||
|
|
d3524a50a3 | ||
|
|
6508a6d5f7 | ||
|
|
49a6cf8ae3 | ||
|
|
b4238e0072 | ||
|
|
374170bf05 | ||
|
|
ab11345c3d | ||
|
|
10498ce1a4 | ||
|
|
28901487ff | ||
|
|
8414f51ee8 | ||
|
|
94f8adb6d7 | ||
|
|
844a921a1a | ||
|
|
ae8be3eda8 | ||
|
|
c4c15dbef8 | ||
|
|
ac72035500 | ||
|
|
abff3bcd39 | ||
|
|
05aea28602 | ||
|
|
e4c4dbf5a0 | ||
|
|
bb2393b6c6 | ||
|
|
fb330d16b5 | ||
|
|
c8f1b986ec | ||
|
|
49a2c93d28 | ||
|
|
0992ac4099 | ||
|
|
9ff29af616 | ||
|
|
fbc696047b | ||
|
|
08a4d4b114 | ||
|
|
329056301b | ||
|
|
fac8da69e7 | ||
|
|
fad9eed43e | ||
|
|
58a18bdd7b | ||
|
|
90cb524560 | ||
|
|
ef4c57ce29 | ||
|
|
8872fad73e | ||
|
|
63c3330571 | ||
|
|
37d1bb9477 | ||
|
|
8a67d1d02b | ||
|
|
6f777068ab | ||
|
|
8607e1c23c | ||
|
|
04a319066c | ||
|
|
39f89ca943 | ||
|
|
1092d7a9ba | ||
|
|
b54052182d | ||
|
|
b971c392cf | ||
|
|
cec9306387 | ||
|
|
f6a5cbbf80 | ||
|
|
4b55c414f3 | ||
|
|
1aafcdc6ae | ||
|
|
332e37b2eb | ||
|
|
dff33d3bab | ||
|
|
85ddc9689c | ||
|
|
d91c207b60 | ||
|
|
653606fae3 | ||
|
|
f5a0c8f375 | ||
|
|
c71019951c | ||
|
|
ed7b79ce17 | ||
|
|
08cfb490d4 | ||
|
|
7d284a85bc | ||
|
|
77ef0a2833 | ||
|
|
80130654ec | ||
|
|
e97f7c8645 | ||
|
|
e489ff6a22 | ||
|
|
de549d724c | ||
|
|
5fb2dbd252 | ||
|
|
20013cf7b7 | ||
|
|
78c3146c78 | ||
|
|
ddd7bb9968 | ||
|
|
68935f1489 | ||
|
|
d9a25e1eb9 | ||
|
|
73a837bab5 | ||
|
|
03be45f5a2 | ||
|
|
692adafd8e | ||
|
|
4ff9eb5219 | ||
|
|
286e9fa315 | ||
|
|
e0b6773d2a | ||
|
|
a7cb8a51a3 | ||
|
|
56c7ffa4df | ||
|
|
1498f902c2 | ||
|
|
eea0dd9081 | ||
|
|
1a8c8c07aa | ||
|
|
3901172757 | ||
|
|
3c9507cb7f | ||
|
|
bfc38807c8 | ||
|
|
6dc3a28026 | ||
|
|
eeb507f04e | ||
|
|
2746547194 | ||
|
|
c9a8e81047 | ||
|
|
d87b8ddd4b | ||
|
|
7dfa7071e3 | ||
|
|
92f0091b1d | ||
|
|
54d8f30bf1 | ||
|
|
f7ef13d594 | ||
|
|
2a1157256b | ||
|
|
213ef5060f | ||
|
|
bc24e263b9 | ||
|
|
8da70c41b2 | ||
|
|
4d81846fe0 | ||
|
|
2afdedd0b6 | ||
|
|
8d944cbb24 | ||
|
|
3ffec94b47 | ||
|
|
9176dc98ee | ||
|
|
9881854d13 | ||
|
|
2e4d1fa448 | ||
|
|
97ca1440b0 | ||
|
|
a4688c4450 | ||
|
|
a7ae2a333a | ||
|
|
823e99bd90 | ||
|
|
e32fccc694 | ||
|
|
dd568ab51d | ||
|
|
17f55e577b | ||
|
|
3f77223e65 | ||
|
|
28aad933c5 | ||
|
|
52ca8396db | ||
|
|
bc941544ae | ||
|
|
e3c3b176eb | ||
|
|
3b0b92b954 | ||
|
|
bfcae03420 | ||
|
|
ad4db1ef37 | ||
|
|
fa1a7fd2f1 | ||
|
|
7eac08d0a1 | ||
|
|
dab984b0d4 | ||
|
|
66361dede2 | ||
|
|
628c62fd4b | ||
|
|
84a7e95856 | ||
|
|
fc256d2c4a | ||
|
|
7f81ceeb7e | ||
|
|
3179644fbc | ||
|
|
274a58bcb0 | ||
|
|
dc7f42b0b6 | ||
|
|
f859627d7f | ||
|
|
ccf12bf028 | ||
|
|
c34e2fdd70 | ||
|
|
ea482c6fad | ||
|
|
54f223b5b0 | ||
|
|
74e083bb62 | ||
|
|
a9c36cd171 | ||
|
|
876b0beb2f | ||
|
|
1f73beb895 | ||
|
|
b13aaacdff | ||
|
|
ba67c122fa | ||
|
|
f16550aa9c | ||
|
|
ba57fbbf85 | ||
|
|
ebedb43e72 | ||
|
|
c10f859919 | ||
|
|
8e6e83dfc6 | ||
|
|
326379d222 | ||
|
|
105e85cc63 | ||
|
|
e21dbc85e8 | ||
|
|
78348a6f9c | ||
|
|
f98b98b4f3 | ||
|
|
d362305a25 | ||
|
|
623cfc671c | ||
|
|
456e2112b8 | ||
|
|
af2fbd1ce3 | ||
|
|
91211f07cb | ||
|
|
9c183e84dd | ||
|
|
5e3cebf4a1 | ||
|
|
9437d23e6e | ||
|
|
925a66a12a | ||
|
|
5db8af72a1 | ||
|
|
2b605eb193 | ||
|
|
f16d10995c | ||
|
|
3ef17404b7 | ||
|
|
1316ac731c | ||
|
|
6283a90217 | ||
|
|
84e8857067 | ||
|
|
05a53d7985 | ||
|
|
94b13b7145 | ||
|
|
3e55a147c7 | ||
|
|
f05ed2571f | ||
|
|
c1a37eb2a4 | ||
|
|
4d8d863780 | ||
|
|
d56eec4ba9 | ||
|
|
a05356d0e1 | ||
|
|
4eea6f7f53 | ||
|
|
24e19cc5f8 | ||
|
|
cd7631451b | ||
|
|
d140130b0d | ||
|
|
f0453943da | ||
|
|
42152ccbb5 | ||
|
|
27f8647243 | ||
|
|
b7d520ded6 | ||
|
|
04088ff366 | ||
|
|
d4dcec1a9b | ||
|
|
c8306616e3 | ||
|
|
b34bdebb5c | ||
|
|
9643cb9f94 | ||
|
|
645b29226e | ||
|
|
c56faba922 | ||
|
|
55a19eacc9 | ||
|
|
464a2350ae | ||
|
|
c44f737c99 | ||
|
|
a8794ce60c | ||
|
|
11329ba786 | ||
|
|
e568bd1af9 | ||
|
|
b3fbfdbf9d | ||
|
|
aec4292203 | ||
|
|
82733ca414 | ||
|
|
887424af80 | ||
|
|
f63a25f582 | ||
|
|
635ec748b3 | ||
|
|
fa510e3ffa | ||
|
|
24a5efd5f8 | ||
|
|
547dd55240 | ||
|
|
774705d9ad | ||
|
|
3d756e271c | ||
|
|
2da9a9c1a8 | ||
|
|
cd67d3c919 | ||
|
|
c080fdb244 | ||
|
|
9ee61812b8 | ||
|
|
bccf0a656b | ||
|
|
47ca66e9c7 | ||
|
|
972315ad00 | ||
|
|
0aa8b63c0c | ||
|
|
e77cf403eb | ||
|
|
df89ab29eb | ||
|
|
6c6829bfd5 | ||
|
|
fa531dce81 | ||
|
|
61bc7ad24a | ||
|
|
ce0964e6a7 | ||
|
|
4979ac9d34 | ||
|
|
912bcdf7f7 | ||
|
|
09174e646b | ||
|
|
0c729cb092 | ||
|
|
61faa4aa09 | ||
|
|
0e7a5428f6 | ||
|
|
8030eb52f3 | ||
|
|
9fc315158f | ||
|
|
971f68b0a1 | ||
|
|
adfc17d5c2 | ||
|
|
5ee2852e4c | ||
|
|
ea1d42fa35 | ||
|
|
f8b90f2c07 | ||
|
|
6dc9821891 | ||
|
|
93a2e9cdbf | ||
|
|
6a9d54d6f0 | ||
|
|
28f0b407b5 | ||
|
|
89ed31ffe0 | ||
|
|
aa481ea094 | ||
|
|
523aaef650 | ||
|
|
a56c4d449d | ||
|
|
1468130477 | ||
|
|
0b5571a065 | ||
|
|
002c221390 | ||
|
|
2272c88d04 | ||
|
|
6a58bd632f | ||
|
|
027a7f798d | ||
|
|
dd4ad6d860 | ||
|
|
3342b8f83f | ||
|
|
5951c74fc4 | ||
|
|
2cae83c84f | ||
|
|
65ac1a2558 | ||
|
|
6e064e1533 | ||
|
|
0d1c3051c8 | ||
|
|
f2885cd96e | ||
|
|
98de0a7acb | ||
|
|
6622d0f4db | ||
|
|
ccc269ab3e | ||
|
|
4008cc2349 | ||
|
|
02bb266762 | ||
|
|
5e64400faf | ||
|
|
da2a444ae8 | ||
|
|
1a22c27326 | ||
|
|
b5a7824179 | ||
|
|
1f84aa9dc7 | ||
|
|
942336e281 | ||
|
|
27cda3a949 | ||
|
|
1d5d105f8a | ||
|
|
5c886d443f | ||
|
|
aa306ad11d | ||
|
|
d1cc0d9aac | ||
|
|
f8e08f76b8 | ||
|
|
27c18fa5ff | ||
|
|
0017e767c9 | ||
|
|
4d742dc9e4 | ||
|
|
96245543e0 | ||
|
|
59767a7c7f | ||
|
|
8766bcbc71 | ||
|
|
47e87736ca | ||
|
|
f8af01de24 | ||
|
|
4b5a1f8009 | ||
|
|
e55773c8d3 | ||
|
|
e83671eee0 | ||
|
|
8b04e36a88 | ||
|
|
76cd06904c | ||
|
|
cac7a60708 | ||
|
|
aef1078e74 | ||
|
|
20c891ee28 | ||
|
|
5bfca6e428 | ||
|
|
5971e48ab6 | ||
|
|
427b4d64ed | ||
|
|
41995b5bdd | ||
|
|
c74e372c76 | ||
|
|
e0650bc6f9 | ||
|
|
0de6a91bab | ||
|
|
54b854eb64 | ||
|
|
47dd3a35ce | ||
|
|
d16f11d9b7 | ||
|
|
ce190ba3f0 | ||
|
|
070419c888 | ||
|
|
5b6489af9f | ||
|
|
84c2c59038 | ||
|
|
8b5efac70a | ||
|
|
f82860ddd9 | ||
|
|
d3af048fd5 | ||
|
|
2b3c908298 | ||
|
|
14f35edb0f | ||
|
|
d0e80f76d6 | ||
|
|
ee155c721c | ||
|
|
8adc43c9a2 | ||
|
|
02d59dc71d | ||
|
|
3edb0f6a5d | ||
|
|
acf9029394 | ||
|
|
10588769b3 | ||
|
|
68a24fae2f | ||
|
|
625ea26b0a | ||
|
|
dc2c73baa6 | ||
|
|
b8db8bffd4 | ||
|
|
6a078e983b | ||
|
|
bdfc74759f | ||
|
|
b13e14c916 | ||
|
|
32adb85c5b | ||
|
|
a51854e5de | ||
|
|
9ce72bbaaa | ||
|
|
544020febf | ||
|
|
9cfc45e495 | ||
|
|
992ed32d7c | ||
|
|
ac4f83b9e0 | ||
|
|
5810d199fc | ||
|
|
8528e5d8f2 | ||
|
|
83d19c30c2 | ||
|
|
646dab336d | ||
|
|
d05e86cd41 | ||
|
|
6d1c5b31f4 | ||
|
|
583cb49949 | ||
|
|
7f5c7b4cd9 | ||
|
|
17350639aa | ||
|
|
edb961085a | ||
|
|
96c5952869 | ||
|
|
2bac1700d1 | ||
|
|
fe2695e6af | ||
|
|
2120eb9574 | ||
|
|
03917a4067 | ||
|
|
bc09a23c84 | ||
|
|
0ed800634c | ||
|
|
ff4ecfe780 | ||
|
|
2691442809 | ||
|
|
18515e2660 | ||
|
|
df5cbaf7ad | ||
|
|
3cacd03ccd | ||
|
|
2ec04dfa9e | ||
|
|
6943956c37 | ||
|
|
26f0f7909e | ||
|
|
2a1682133b | ||
|
|
02897f312e | ||
|
|
7d4d4cf5c0 | ||
|
|
1fcf797bfe | ||
|
|
b94d417157 | ||
|
|
330227d09b | ||
|
|
67f1ffe617 | ||
|
|
220d7a5ea2 | ||
|
|
e781e00256 | ||
|
|
e630333e8d | ||
|
|
7eb827a219 | ||
|
|
e251b4bc01 | ||
|
|
644f9e1f78 | ||
|
|
396d90c499 | ||
|
|
ff6e93ea2c | ||
|
|
fb97617de6 | ||
|
|
ff47ab0a04 | ||
|
|
ff98dae886 | ||
|
|
deae7681f8 | ||
|
|
849c1d8bec | ||
|
|
b88f0e9a82 | ||
|
|
5ea2972ca1 | ||
|
|
08ad6aaa85 | ||
|
|
8ba32a0196 | ||
|
|
68ce3ce01c | ||
|
|
fb47beb380 | ||
|
|
73a1464d5b | ||
|
|
75b1225b38 | ||
|
|
07a4c4b7a4 | ||
|
|
cbf9295225 | ||
|
|
19d7fae814 | ||
|
|
d9db571362 | ||
|
|
91e44d9418 | ||
|
|
e30b95dd6c | ||
|
|
ddf27e619d | ||
|
|
ebbcbf324f | ||
|
|
c161d4d781 | ||
|
|
da01730c73 | ||
|
|
f0d76f1bc2 | ||
|
|
3d5b1d00f0 | ||
|
|
a098839060 | ||
|
|
d3fac95701 | ||
|
|
37590dc5ee | ||
|
|
8dfbc0b5e6 | ||
|
|
0a9b292d12 | ||
|
|
e7d4228c0c | ||
|
|
a1836e5433 | ||
|
|
52e0496e36 | ||
|
|
50e6e28277 | ||
|
|
4cf770837b | ||
|
|
38fb9f7fb8 | ||
|
|
7a6232c8b6 | ||
|
|
13e62f3b38 | ||
|
|
d5590d37e3 | ||
|
|
fd21806456 | ||
|
|
34bbfffdaf | ||
|
|
56bbb4a786 | ||
|
|
2b92d200ca | ||
|
|
d4154e51d3 | ||
|
|
7d69e63dc9 | ||
|
|
0189f13ee6 | ||
|
|
11e32712f3 | ||
|
|
d124894d34 | ||
|
|
84bfcf2b3f | ||
|
|
8e96096353 | ||
|
|
a4739b2001 | ||
|
|
d3f5f33b53 | ||
|
|
11bb1aa126 | ||
|
|
688010cae4 | ||
|
|
150482eb56 | ||
|
|
c5e98c62ec | ||
|
|
7b2f8885b1 | ||
|
|
d4a7c33787 | ||
|
|
0cd245cafc | ||
|
|
7487993537 | ||
|
|
33b7829b88 | ||
|
|
7531853548 | ||
|
|
3b77cf6f8a | ||
|
|
7b0f459337 | ||
|
|
b498ffd66e | ||
|
|
6c8440a95f | ||
|
|
6bb8cc8bc9 | ||
|
|
dad531876a | ||
|
|
205a629071 | ||
|
|
b7704cc55e | ||
|
|
84ddbef585 | ||
|
|
3bed947ba9 | ||
|
|
23d2faf107 | ||
|
|
b1d06a0be1 | ||
|
|
83ad3e2200 | ||
|
|
84dcce6018 | ||
|
|
d447ea7ff8 | ||
|
|
91f8856efe | ||
|
|
77e45626bb | ||
|
|
a61304a72a | ||
|
|
7336075860 | ||
|
|
6dbd70fced | ||
|
|
81c7d8a259 | ||
|
|
a6a899e696 | ||
|
|
4ae314b3a0 | ||
|
|
16ac55fd67 | ||
|
|
c659065986 | ||
|
|
f1a6b5a7a8 | ||
|
|
036de26e2a | ||
|
|
5ca0919546 | ||
|
|
4430df50fe | ||
|
|
4ff7913283 | ||
|
|
0376245dbc | ||
|
|
3052c40359 | ||
|
|
64af34ca71 | ||
|
|
aba95bbd8a | ||
|
|
5de2a40a54 | ||
|
|
c12c5a6cc4 | ||
|
|
8674520d46 | ||
|
|
06d3a5fe54 | ||
|
|
6c485af249 | ||
|
|
f0ed989463 | ||
|
|
05de9d6941 | ||
|
|
2ddebc5970 | ||
|
|
f1265bf84e | ||
|
|
dc4c4be4c7 | ||
|
|
d5100b97f3 | ||
|
|
31dc05f6b2 | ||
|
|
ca7ee9e694 | ||
|
|
7acc2e28cd | ||
|
|
7eff64bf26 | ||
|
|
d5d3cfa4e8 | ||
|
|
2b937eda7c | ||
|
|
118b5a90b6 | ||
|
|
d9c9295220 | ||
|
|
eb4b6f276e | ||
|
|
52e68df515 | ||
|
|
c23973086c | ||
|
|
34be79f3d2 | ||
|
|
a8082748ad | ||
|
|
08a4de919f | ||
|
|
7ce54ec0d3 | ||
|
|
ce7dad0c8e | ||
|
|
e059ed361d | ||
|
|
d12d641913 | ||
|
|
5336b37133 | ||
|
|
1819476a71 | ||
|
|
e2c621ec1f | ||
|
|
854bca27ae | ||
|
|
b1dd9fa38a | ||
|
|
8776ed61e9 | ||
|
|
c35fe166ed | ||
|
|
0126b6d6da | ||
|
|
4ecb877e27 | ||
|
|
4f7f72f213 |
4
.github/workflows/android.yml
vendored
4
.github/workflows/android.yml
vendored
@@ -3,12 +3,12 @@ name: Android CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- staging
|
||||
- trying
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: Compress Images on Push to Master
|
||||
name: Compress Images on Push to Main
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
paths:
|
||||
- '**.jpg'
|
||||
- '**.jpeg'
|
||||
|
||||
2
.github/workflows/changelog-to-fastlane.yml
vendored
2
.github/workflows/changelog-to-fastlane.yml
vendored
@@ -2,7 +2,7 @@ name: Convert CHANGELOG to Fastlane
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
jobs:
|
||||
convert_changelog_to_fastlane:
|
||||
|
||||
73
.github/workflows/codeql-analysis.yml
vendored
73
.github/workflows/codeql-analysis.yml
vendored
@@ -1,73 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
- cron: '33 1 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
2
.github/workflows/contributors-to-file.yml
vendored
2
.github/workflows/contributors-to-file.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
jobs:
|
||||
contributors_to_file:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
if: github.ref == 'refs/heads/main'
|
||||
name: Write contributors to file
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
|
||||
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -8,3 +8,8 @@ captures/
|
||||
**/release
|
||||
**/debug
|
||||
app/*.log
|
||||
|
||||
# Bundle
|
||||
/.bundle/
|
||||
/vendor/bundle
|
||||
/lib/bundler/man/
|
||||
|
||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -1,5 +1,52 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased - 118
|
||||
|
||||
- Support setting start of card validity
|
||||
|
||||
## v2.21.2 - 117
|
||||
|
||||
- Remove unnecessary permissions
|
||||
- Target Android 13
|
||||
|
||||
## v2.21.1 - 116
|
||||
|
||||
- Fix quick spend dialog not allowing , separator
|
||||
- Support loading image from file manager
|
||||
|
||||
## v2.21.0 - 115
|
||||
|
||||
- Open image in gallery on long-press
|
||||
- Apply Material style to dialogs
|
||||
- Support creating card by sharing an image to Catima
|
||||
- Add quick spend button to card screen
|
||||
|
||||
## v2.20.0 - 114
|
||||
|
||||
- Add Monochrome icon for Android 13
|
||||
- Improve first launch screen
|
||||
- Fidme import fixes
|
||||
|
||||
## v2.19.0 - 113
|
||||
|
||||
- Add previous and next buttons to the loyalty card view
|
||||
- Fix foreground colour on edit button
|
||||
- Replace floppy disk save icon with checkmark
|
||||
|
||||
## v2.18.2 - 112
|
||||
|
||||
- Make the possibility to set a custom header more visible
|
||||
|
||||
## v2.18.1 - 111
|
||||
|
||||
- Arabic language support
|
||||
- Display archived card count in group overview
|
||||
- Fix balance parsing bugs (made cards not savable in Arabic and other language with non-Western numbers)
|
||||
- Fix custom theme not applying to main screen correctly
|
||||
- Improve display of selected cards
|
||||
- Fix crash when leaving cardview in RTL layouts for cards with expiry or balance
|
||||
- Fix back arrow in card view pointing the wrong way in RTL layouts
|
||||
|
||||
## v2.17.1 - 109
|
||||
|
||||
- Fix incorrect text colour on "No barcode" button
|
||||
@@ -566,7 +613,7 @@ Additional features/improvements:
|
||||
## v0.7 - 7 (2016-07-14)
|
||||
|
||||
- Long-click of a card brings up option to copy card ID to the clipboard. ([pull #49](https://github.com/brarcher/loyalty-card-locker/issues/49))
|
||||
- Back button on Input/Export view now works, moving user to main view
|
||||
- Back button on Import/Export view now works, moving user to main view
|
||||
|
||||
## v0.6 - 6 (2016-05-23)
|
||||
|
||||
|
||||
@@ -8,7 +8,20 @@ to the rules described here, but by following the instructions below you
|
||||
should have a much easier time getting your work merged with the upstream
|
||||
project.
|
||||
|
||||
## Test Your Code
|
||||
## Translation Changes
|
||||
|
||||
Translation changes are managed through [Weblate](https://hosted.weblate.org/projects/catima/).
|
||||
Please do not supply translation updates directly through GitHub.
|
||||
|
||||
Weblate requires an account to translate changes, so please log in before
|
||||
you start translating.
|
||||
|
||||
While using Weblate, please do not ignore any of its warnings. They exist
|
||||
for good reason.
|
||||
|
||||
## Code Changes
|
||||
|
||||
### Test Your Code
|
||||
|
||||
There are four possible tests you can run to verify your code. The first
|
||||
is unit tests, which check the basic functionality of the application, and
|
||||
@@ -28,14 +41,14 @@ and SpotBugs, run using:
|
||||
The final check is by testing the application on a live device and verifying
|
||||
the basic functionality works as expected.
|
||||
|
||||
## Make Sure Your Code is Tested
|
||||
### Make Sure Your Code is Tested
|
||||
|
||||
The Catima code uses a fair number of unit tests to verify that
|
||||
the basic functionality is working. Submissions which add functionality
|
||||
or significantly change the existing code should include additional tests
|
||||
to verify the proper operation of the proposed changes.
|
||||
|
||||
## Explain Your Work
|
||||
### Explain Your Work
|
||||
|
||||
At the top of every patch you should include a description of the problem you
|
||||
are trying to solve, how you solved it, and why you chose the solution you
|
||||
@@ -44,7 +57,7 @@ if you can describe/include a reproducer for the problem in the description as
|
||||
well as instructions on how to test for the bug and verify that it has been
|
||||
fixed.
|
||||
|
||||
## Sign Your Work
|
||||
### Sign Your Work
|
||||
|
||||
The sign-off is a simple line at the end of the patch description, which
|
||||
certifies that you wrote it or otherwise have the right to pass it on as an
|
||||
@@ -82,10 +95,10 @@ your real name, saying:
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
## Submit Patch(es) for Review
|
||||
### Submit Patch(es) for Review
|
||||
|
||||
Finally, you will need to submit your patches so that they can be reviewed
|
||||
and potentially merged into the main Catima repository. The preferred
|
||||
way to do this is to submit a Pull Request to the Catima project.
|
||||
Changes need to apply cleanly onto the master branch and pass all
|
||||
Changes need to apply cleanly onto the main branch and pass all
|
||||
unit tests and produce no errors during static analysis.
|
||||
|
||||
80
Gemfile.lock
80
Gemfile.lock
@@ -1,27 +1,27 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.5)
|
||||
CFPropertyList (3.0.6)
|
||||
rexml
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.597.0)
|
||||
aws-sdk-core (3.131.1)
|
||||
aws-partitions (1.701.0)
|
||||
aws-sdk-core (3.170.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.525.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.57.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
aws-sdk-kms (1.62.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.114.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
aws-sdk-s3 (1.119.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.4)
|
||||
aws-sigv4 (1.5.0)
|
||||
aws-sigv4 (1.5.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
claide (1.1.0)
|
||||
@@ -34,10 +34,10 @@ GEM
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.6)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.92.3)
|
||||
faraday (1.10.0)
|
||||
excon (0.98.0)
|
||||
faraday (1.10.3)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
@@ -66,7 +66,7 @@ GEM
|
||||
faraday_middleware (1.2.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.206.2)
|
||||
fastlane (2.211.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@@ -106,9 +106,9 @@ GEM
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.21.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-core (0.5.0)
|
||||
google-apis-androidpublisher_v3 (0.32.0)
|
||||
google-apis-core (>= 0.9.1, < 2.a)
|
||||
google-apis-core (0.10.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
@@ -117,27 +117,27 @@ GEM
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
webrick
|
||||
google-apis-iamcredentials_v1 (0.10.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.7.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-storage_v1 (0.14.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-iamcredentials_v1 (0.16.0)
|
||||
google-apis-core (>= 0.9.1, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.12.0)
|
||||
google-apis-core (>= 0.9.1, < 2.a)
|
||||
google-apis-storage_v1 (0.19.0)
|
||||
google-apis-core (>= 0.9.0, < 2.a)
|
||||
google-cloud-core (1.6.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.2.0)
|
||||
google-cloud-storage (1.36.2)
|
||||
google-cloud-errors (1.3.0)
|
||||
google-cloud-storage (1.44.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.19.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.1.3)
|
||||
googleauth (1.3.0)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
@@ -148,11 +148,11 @@ GEM
|
||||
http-cookie (1.0.5)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.1)
|
||||
json (2.6.2)
|
||||
jwt (2.4.1)
|
||||
jmespath (1.6.2)
|
||||
json (2.6.3)
|
||||
jwt (2.6.0)
|
||||
memoist (0.16.2)
|
||||
mini_magick (4.11.0)
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.2)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.0.0)
|
||||
@@ -161,7 +161,7 @@ GEM
|
||||
optparse (0.1.1)
|
||||
os (1.1.4)
|
||||
plist (3.6.0)
|
||||
public_suffix (4.0.7)
|
||||
public_suffix (5.0.1)
|
||||
rake (13.0.6)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
@@ -173,12 +173,12 @@ GEM
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.3)
|
||||
signet (0.16.1)
|
||||
signet (0.17.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.0)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.8)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
terminal-notifier (2.0.0)
|
||||
@@ -194,9 +194,9 @@ GEM
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (1.8.0)
|
||||
webrick (1.7.0)
|
||||
webrick (1.8.1)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.21.0)
|
||||
xcodeproj (1.22.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
@@ -215,4 +215,4 @@ DEPENDENCIES
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
2.3.26
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import com.github.spotbugs.snom.SpotBugsTask
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'com.github.spotbugs'
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'com.github.spotbugs'
|
||||
}
|
||||
|
||||
spotbugs {
|
||||
ignoreFailures = false
|
||||
@@ -11,15 +13,14 @@ spotbugs {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
buildToolsVersion "31.0.0"
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "me.hackerchick.catima"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 109
|
||||
versionName "2.17.1"
|
||||
minSdk 21
|
||||
targetSdk 33
|
||||
versionCode 117
|
||||
versionName "2.21.2"
|
||||
|
||||
vectorDrawables.useSupportLibrary true
|
||||
multiDexEnabled true
|
||||
@@ -37,6 +38,10 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
bundle {
|
||||
language {
|
||||
enableSplit = false
|
||||
@@ -54,8 +59,7 @@ android {
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable "GoogleAppIndexingWarning", "ButtonStyle", "AlwaysShowAction",
|
||||
"MissingTranslation", "MissingPrefix"
|
||||
lintConfig file("lint.xml")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -80,33 +84,33 @@ android {
|
||||
|
||||
dependencies {
|
||||
// AndroidX
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.5'
|
||||
implementation 'androidx.palette:palette:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'com.github.yalantis:ucrop:2.2.8'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
|
||||
|
||||
// Splash Screen
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0-rc01'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.0'
|
||||
|
||||
// Third-party
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
|
||||
implementation 'com.google.zxing:core:3.5.0'
|
||||
implementation 'com.google.zxing:core:3.5.1'
|
||||
implementation 'org.apache.commons:commons-csv:1.9.0'
|
||||
implementation 'com.jaredrummler:colorpicker:1.1.0'
|
||||
implementation 'com.github.invissvenska:NumberPickerPreference:1.0.4'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.11.1'
|
||||
implementation 'net.lingala.zip4j:zip4j:2.11.5'
|
||||
|
||||
// SpotBugs
|
||||
implementation 'io.wcm.tooling.spotbugs:io.wcm.tooling.spotbugs.annotations:1.0.0'
|
||||
|
||||
// Testing
|
||||
testImplementation 'androidx.test:core:1.4.0'
|
||||
testImplementation 'androidx.test:core:1.5.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.robolectric:robolectric:4.8.1'
|
||||
testImplementation 'org.robolectric:robolectric:4.9.2'
|
||||
}
|
||||
|
||||
tasks.withType(SpotBugsTask) {
|
||||
|
||||
@@ -6,5 +6,8 @@
|
||||
<Match>
|
||||
<Class name="~.*Manifest\$.*"/>
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="~.*Binding" />
|
||||
</Match>
|
||||
|
||||
</FindBugsFilter>
|
||||
|
||||
8
app/lint.xml
Normal file
8
app/lint.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
<issue id="AlwaysShowAction" severity="ignore" />
|
||||
<issue id="ButtonStyle" severity="ignore" />
|
||||
<issue id="GoogleAppIndexingWarning" severity="ignore" />
|
||||
<issue id="MissingTranslation" severity="ignore" />
|
||||
<issue id="MissingPrefix" severity="ignore" />
|
||||
</lint>
|
||||
@@ -6,8 +6,7 @@
|
||||
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="23" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
@@ -33,6 +32,12 @@
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="image/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
@@ -102,7 +107,39 @@
|
||||
<activity
|
||||
android:name=".ImportExportActivity"
|
||||
android:label="@string/importExport"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
android:exported="true"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
|
||||
<!-- ZIP Intent Filter -->
|
||||
<intent-filter
|
||||
android:label="@string/importCards">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/zip" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:host="*"/>
|
||||
</intent-filter>
|
||||
|
||||
<!-- JSON Intent Filter -->
|
||||
<intent-filter
|
||||
android:label="@string/importCards">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="application/json" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:host="*"/>
|
||||
</intent-filter>
|
||||
|
||||
<!-- CSV Intent Filter -->
|
||||
<intent-filter
|
||||
android:label="@string/importCards">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:host="*" />
|
||||
<data android:mimeType="text/comma-separated-values" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".CardShortcutConfigure"
|
||||
android:exported="true"
|
||||
|
||||
@@ -1,135 +1,46 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
public class AboutActivity extends CatimaAppCompatActivity implements View.OnClickListener {
|
||||
import protect.card_locker.databinding.AboutActivityBinding;
|
||||
|
||||
public class AboutActivity extends CatimaAppCompatActivity {
|
||||
|
||||
private static final String TAG = "Catima";
|
||||
ConstraintLayout version_history, translate, license, repo, privacy, error, credits, rate;
|
||||
|
||||
private AboutActivityBinding binding;
|
||||
private AboutContent content;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.about);
|
||||
setContentView(R.layout.about_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
binding = AboutActivityBinding.inflate(getLayoutInflater());
|
||||
content = new AboutContent(this);
|
||||
setTitle(content.getPageTitle());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
enableToolbarBackButton();
|
||||
|
||||
StringBuilder contributors = new StringBuilder().append("<br/>");
|
||||
TextView copyright = binding.creditsSub;
|
||||
copyright.setText(content.getCopyright());
|
||||
TextView versionHistory = binding.versionHistorySub;
|
||||
versionHistory.setText(content.getVersionHistory());
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.contributors), StandardCharsets.UTF_8));
|
||||
binding.versionHistory.setTag("https://catima.app/changelog/");
|
||||
binding.translate.setTag("https://hosted.weblate.org/engage/catima/");
|
||||
binding.license.setTag("https://github.com/CatimaLoyalty/Android/blob/main/LICENSE");
|
||||
binding.repo.setTag("https://github.com/CatimaLoyalty/Android/");
|
||||
binding.privacy.setTag("https://catima.app/privacy-policy/");
|
||||
binding.reportError.setTag("https://github.com/CatimaLoyalty/Android/issues");
|
||||
binding.rate.setTag("https://play.google.com/store/apps/details?id=me.hackerchick.catima");
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
String tmp = reader.readLine();
|
||||
|
||||
if (tmp == null || tmp.isEmpty()) {
|
||||
reader.close();
|
||||
break;
|
||||
}
|
||||
|
||||
contributors.append("<br/>");
|
||||
contributors.append(tmp);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
final List<ThirdPartyInfo> USED_LIBRARIES = new ArrayList<>();
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0"));
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0"));
|
||||
USED_LIBRARIES.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0"));
|
||||
|
||||
final List<ThirdPartyInfo> USED_ASSETS = new ArrayList<>();
|
||||
USED_ASSETS.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
|
||||
|
||||
StringBuilder libs = new StringBuilder().append("<br/>");
|
||||
for (ThirdPartyInfo entry : USED_LIBRARIES) {
|
||||
libs.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
|
||||
}
|
||||
|
||||
StringBuilder resources = new StringBuilder().append("<br/>");
|
||||
for (ThirdPartyInfo entry : USED_ASSETS) {
|
||||
resources.append("<br/><a href=\"").append(entry.url()).append("\">").append(entry.name()).append("</a> (").append(entry.license()).append(")");
|
||||
}
|
||||
|
||||
String appName = getString(R.string.app_name);
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
|
||||
String version = "?";
|
||||
try {
|
||||
PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
version = pi.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, "Package name not found", e);
|
||||
}
|
||||
|
||||
TextView copyright = findViewById(R.id.credits_sub);
|
||||
copyright.setText(String.format(getString(R.string.app_copyright_fmt), year));
|
||||
TextView vHistory = findViewById(R.id.version_history_sub);
|
||||
vHistory.setText(String.format(getString(R.string.debug_version_fmt), version));
|
||||
|
||||
setTitle(String.format(getString(R.string.about_title_fmt), appName));
|
||||
|
||||
version_history = findViewById(R.id.version_history);
|
||||
translate = findViewById(R.id.translate);
|
||||
license = findViewById(R.id.license);
|
||||
repo = findViewById(R.id.repo);
|
||||
privacy = findViewById(R.id.privacy);
|
||||
error = findViewById(R.id.report_error);
|
||||
credits = findViewById(R.id.credits);
|
||||
rate = findViewById(R.id.rate);
|
||||
|
||||
version_history.setOnClickListener(this);
|
||||
translate.setOnClickListener(this);
|
||||
license.setOnClickListener(this);
|
||||
repo.setOnClickListener(this);
|
||||
privacy.setOnClickListener(this);
|
||||
error.setOnClickListener(this);
|
||||
rate.setOnClickListener(this);
|
||||
|
||||
StringBuilder contributorInfo = new StringBuilder();
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_contributors), contributors.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(getString(R.string.app_copyright_old));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_libraries), libs.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(getString(R.string.app_resources), resources.toString()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
|
||||
credits.setOnClickListener(view -> new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.credits)
|
||||
.setMessage(contributorInfo.toString())
|
||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
})
|
||||
.show());
|
||||
bindClickListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,31 +53,47 @@ public class AboutActivity extends CatimaAppCompatActivity implements View.OnCli
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
int id = view.getId();
|
||||
|
||||
String url;
|
||||
if (id == R.id.version_history) {
|
||||
url = "https://catima.app/changelog/";
|
||||
} else if (id == R.id.translate) {
|
||||
url = "https://hosted.weblate.org/engage/catima/";
|
||||
} else if (id == R.id.license) {
|
||||
url = "https://github.com/CatimaLoyalty/Android/blob/master/LICENSE";
|
||||
} else if (id == R.id.repo) {
|
||||
url = "https://github.com/CatimaLoyalty/Android/";
|
||||
} else if (id == R.id.privacy) {
|
||||
url = "https://catima.app/privacy-policy/";
|
||||
} else if (id == R.id.report_error) {
|
||||
url = "https://github.com/CatimaLoyalty/Android/issues";
|
||||
} else if (id == R.id.rate) {
|
||||
url = "https://play.google.com/store/apps/details?id=me.hackerchick.catima";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
content.destroy();
|
||||
clearClickListeners();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void bindClickListeners() {
|
||||
View.OnClickListener openExternalBrowser = view -> {
|
||||
Object tag = view.getTag();
|
||||
if (tag instanceof String && ((String) tag).startsWith("https://")) {
|
||||
(new OpenWebLinkHandler()).openBrowser(this, (String) tag);
|
||||
}
|
||||
};
|
||||
binding.versionHistory.setOnClickListener(openExternalBrowser);
|
||||
binding.translate.setOnClickListener(openExternalBrowser);
|
||||
binding.license.setOnClickListener(openExternalBrowser);
|
||||
binding.repo.setOnClickListener(openExternalBrowser);
|
||||
binding.privacy.setOnClickListener(openExternalBrowser);
|
||||
binding.reportError.setOnClickListener(openExternalBrowser);
|
||||
binding.rate.setOnClickListener(openExternalBrowser);
|
||||
|
||||
binding.credits.setOnClickListener(view -> showCredits());
|
||||
}
|
||||
|
||||
private void clearClickListeners() {
|
||||
binding.versionHistory.setOnClickListener(null);
|
||||
binding.translate.setOnClickListener(null);
|
||||
binding.license.setOnClickListener(null);
|
||||
binding.repo.setOnClickListener(null);
|
||||
binding.privacy.setOnClickListener(null);
|
||||
binding.reportError.setOnClickListener(null);
|
||||
binding.rate.setOnClickListener(null);
|
||||
binding.credits.setOnClickListener(null);
|
||||
}
|
||||
|
||||
private void showCredits() {
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.credits)
|
||||
.setMessage(content.getContributorInfo())
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
111
app/src/main/java/protect/card_locker/AboutContent.java
Normal file
111
app/src/main/java/protect/card_locker/AboutContent.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
public class AboutContent {
|
||||
|
||||
public static final String TAG = "Catima";
|
||||
|
||||
public Context context;
|
||||
|
||||
public AboutContent(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
public String getPageTitle() {
|
||||
return String.format(context.getString(R.string.about_title_fmt), context.getString(R.string.app_name));
|
||||
}
|
||||
|
||||
public String getAppVersion() {
|
||||
String version = "?";
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
version = pi.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, "Package name not found", e);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public int getCurrentYear() {
|
||||
return Calendar.getInstance().get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
public String getCopyright() {
|
||||
return String.format(context.getString(R.string.app_copyright_fmt), getCurrentYear());
|
||||
}
|
||||
|
||||
public String getContributors() {
|
||||
String contributors;
|
||||
try {
|
||||
contributors = "<br/>" + Utils.readTextFile(context, R.raw.contributors);
|
||||
} catch (IOException ignored) {
|
||||
return "";
|
||||
}
|
||||
return contributors.replace("\n", "<br />");
|
||||
}
|
||||
|
||||
public String getThirdPartyLibraries() {
|
||||
final List<ThirdPartyInfo> usedLibraries = new ArrayList<>();
|
||||
usedLibraries.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("uCrop", "https://github.com/Yalantis/uCrop", "Apache 2.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0"));
|
||||
usedLibraries.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0"));
|
||||
|
||||
StringBuilder result = new StringBuilder("<br/>");
|
||||
for (ThirdPartyInfo entry : usedLibraries) {
|
||||
result.append("<br/>")
|
||||
.append(entry.toHtml());
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String getUsedThirdPartyAssets() {
|
||||
final List<ThirdPartyInfo> usedAssets = new ArrayList<>();
|
||||
usedAssets.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0"));
|
||||
|
||||
StringBuilder result = new StringBuilder().append("<br/>");
|
||||
for (ThirdPartyInfo entry : usedAssets) {
|
||||
result.append("<br/>")
|
||||
.append(entry.toHtml());
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String getContributorInfo() {
|
||||
StringBuilder contributorInfo = new StringBuilder();
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_contributors), getContributors()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(context.getString(R.string.app_copyright_old));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_libraries), getThirdPartyLibraries()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
contributorInfo.append("\n\n");
|
||||
contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_resources), getUsedThirdPartyAssets()), HtmlCompat.FROM_HTML_MODE_COMPACT));
|
||||
|
||||
return contributorInfo.toString();
|
||||
}
|
||||
|
||||
public String getVersionHistory() {
|
||||
return String.format(context.getString(R.string.debug_version_fmt), getAppVersion());
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import java.util.ArrayList;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import protect.card_locker.databinding.BarcodeSelectorActivityBinding;
|
||||
|
||||
/**
|
||||
* This activity is callable and will allow a user to enter
|
||||
* barcode data and generate all barcodes possible for
|
||||
@@ -26,6 +28,7 @@ import androidx.appcompat.widget.Toolbar;
|
||||
* data and type will be returned to the caller.
|
||||
*/
|
||||
public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements BarcodeSelectorAdapter.BarcodeSelectorListener {
|
||||
private BarcodeSelectorActivityBinding binding;
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
// Result this activity will return
|
||||
@@ -40,17 +43,15 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = BarcodeSelectorActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.selectBarcodeTitle);
|
||||
setContentView(R.layout.barcode_selector_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
EditText cardId = findViewById(R.id.cardId);
|
||||
ListView mBarcodeList = findViewById(R.id.barcodes);
|
||||
EditText cardId = binding.cardId;
|
||||
ListView mBarcodeList = binding.barcodes;
|
||||
mAdapter = new BarcodeSelectorAdapter(this, new ArrayList<>(), this);
|
||||
mBarcodeList.setAdapter(mAdapter);
|
||||
|
||||
@@ -66,7 +67,7 @@ public class BarcodeSelectorActivity extends CatimaAppCompatActivity implements
|
||||
runOnUiThread(() -> {
|
||||
generateBarcodes(s.toString());
|
||||
|
||||
View noBarcodeButtonView = findViewById(R.id.noBarcode);
|
||||
View noBarcodeButtonView = binding.noBarcode;
|
||||
setButtonListener(noBarcodeButtonView, s.toString());
|
||||
noBarcodeButtonView.setEnabled(s.length() > 0);
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.widget.TextView;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.databinding.BarcodeLayoutBinding;
|
||||
|
||||
public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue> {
|
||||
private static final String TAG = "Catima";
|
||||
@@ -51,9 +52,10 @@ public class BarcodeSelectorAdapter extends ArrayAdapter<CatimaBarcodeWithValue>
|
||||
if (convertView == null) {
|
||||
viewHolder = new ViewHolder();
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
convertView = inflater.inflate(R.layout.barcode_layout, parent, false);
|
||||
viewHolder.image = convertView.findViewById(R.id.barcodeImage);
|
||||
viewHolder.text = convertView.findViewById(R.id.barcodeName);
|
||||
BarcodeLayoutBinding barcodeLayoutBinding = BarcodeLayoutBinding.inflate(inflater, parent, false);
|
||||
convertView = barcodeLayoutBinding.getRoot();
|
||||
viewHolder.image = barcodeLayoutBinding.barcodeImage;
|
||||
viewHolder.text = barcodeLayoutBinding.barcodeName;
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
|
||||
@@ -8,17 +8,19 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.pm.ShortcutInfoCompat;
|
||||
import androidx.core.content.pm.ShortcutManagerCompat;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.databinding.SimpleToolbarListActivityBinding;
|
||||
|
||||
/**
|
||||
* The configuration screen for creating a shortcut.
|
||||
*/
|
||||
public class CardShortcutConfigure extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener {
|
||||
private SimpleToolbarListActivityBinding binding;
|
||||
static final String TAG = "Catima";
|
||||
private SQLiteDatabase mDatabase;
|
||||
private LoyaltyCardCursorAdapter mAdapter;
|
||||
@@ -26,15 +28,15 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
binding = SimpleToolbarListActivityBinding.inflate(getLayoutInflater());
|
||||
mDatabase = new DBHelper(this).getReadableDatabase();
|
||||
|
||||
// Set the result to CANCELED. This will cause nothing to happen if the
|
||||
// aback button is pressed.
|
||||
setResult(RESULT_CANCELED);
|
||||
|
||||
setContentView(R.layout.simple_toolbar_list_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
toolbar.setTitle(R.string.shortcutSelectCard);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
@@ -51,7 +53,7 @@ public class CardShortcutConfigure extends CatimaAppCompatActivity implements Lo
|
||||
finish();
|
||||
}
|
||||
|
||||
final RecyclerView cardList = findViewById(R.id.list);
|
||||
final RecyclerView cardList = binding.list;
|
||||
GridLayoutManager layoutManager = (GridLayoutManager) cardList.getLayoutManager();
|
||||
if (layoutManager != null) {
|
||||
layoutManager.setSpanCount(getResources().getInteger(R.integer.main_view_card_columns));
|
||||
|
||||
@@ -16,13 +16,13 @@ import android.service.controls.actions.ControlAction;
|
||||
import android.service.controls.templates.StatelessTemplate;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
public class CardsOnPowerScreenService extends ControlsProviderService {
|
||||
|
||||
@@ -137,7 +137,7 @@ public class CardsOnPowerScreenService extends ControlsProviderService {
|
||||
closePowerScreenOnAndroid11();
|
||||
}
|
||||
|
||||
@SuppressLint({"MissingPermission", "deprecation"})
|
||||
@SuppressWarnings({"MissingPermission", "deprecation"})
|
||||
private void closePowerScreenOnAndroid11() {
|
||||
// Android 12 will auto-close the power screen, but earlier versions won't
|
||||
// Lint complains about this but on Android 11 the permission is not needed
|
||||
|
||||
@@ -6,8 +6,11 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
public class CatimaAppCompatActivity extends AppCompatActivity {
|
||||
@Override
|
||||
@@ -19,10 +22,7 @@ public class CatimaAppCompatActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// XXX splash screen activity has to do this after installing splash screen before view inflate
|
||||
if (!this.getClass().getSimpleName().equals(MainActivity.class.getSimpleName())) {
|
||||
Utils.patchColors(this);
|
||||
}
|
||||
Utils.patchColors(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,8 +32,10 @@ public class CatimaAppCompatActivity extends AppCompatActivity {
|
||||
// XXX changing this in onCreate causes issues with the splash screen activity, so doing this here
|
||||
boolean darkMode = Utils.isDarkModeEnabled(this);
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
View decorView = getWindow().getDecorView();
|
||||
WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView);
|
||||
wic.setAppearanceLightStatusBars(!darkMode);
|
||||
getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
} else {
|
||||
// icons are always white back then
|
||||
getWindow().setStatusBarColor(darkMode ? Color.TRANSPARENT : Color.argb(127, 0, 0, 0));
|
||||
@@ -41,4 +43,14 @@ public class CatimaAppCompatActivity extends AppCompatActivity {
|
||||
// XXX android 9 and below has a nasty rendering bug if the theme was patched earlier
|
||||
Utils.postPatchColors(this);
|
||||
}
|
||||
|
||||
protected void enableToolbarBackButton() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,12 @@ import java.util.List;
|
||||
public class DBHelper extends SQLiteOpenHelper {
|
||||
public static final String DATABASE_NAME = "Catima.db";
|
||||
public static final int ORIGINAL_DATABASE_VERSION = 1;
|
||||
public static final int DATABASE_VERSION = 15;
|
||||
public static final int DATABASE_VERSION = 17;
|
||||
|
||||
public static class LoyaltyCardDbGroups {
|
||||
public static final String TABLE = "groups";
|
||||
public static final String ID = "_id";
|
||||
public static final String NAME = "name";
|
||||
public static final String ORDER = "orderId";
|
||||
}
|
||||
|
||||
@@ -33,6 +34,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
public static final String TABLE = "cards";
|
||||
public static final String ID = "_id";
|
||||
public static final String STORE = "store";
|
||||
public static final String VALID_FROM = "validfrom";
|
||||
public static final String EXPIRY = "expiry";
|
||||
public static final String BALANCE = "balance";
|
||||
public static final String BALANCE_TYPE = "balancetype";
|
||||
@@ -86,7 +88,8 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
// create table for card groups
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
|
||||
LoyaltyCardDbGroups.ID + " TEXT primary key not null," +
|
||||
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
|
||||
LoyaltyCardDbGroups.NAME + " TEXT not null," +
|
||||
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
|
||||
|
||||
// create table for cards
|
||||
@@ -95,6 +98,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
LoyaltyCardDbIds.ID + " INTEGER primary key autoincrement," +
|
||||
LoyaltyCardDbIds.STORE + " TEXT not null," +
|
||||
LoyaltyCardDbIds.NOTE + " TEXT not null," +
|
||||
LoyaltyCardDbIds.VALID_FROM + " INTEGER," +
|
||||
LoyaltyCardDbIds.EXPIRY + " INTEGER," +
|
||||
LoyaltyCardDbIds.BALANCE + " TEXT not null DEFAULT '0'," +
|
||||
LoyaltyCardDbIds.BALANCE_TYPE + " TEXT," +
|
||||
@@ -110,7 +114,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
// create associative table for cards in groups
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " TEXT," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
|
||||
|
||||
// create FTS search table
|
||||
@@ -314,6 +318,75 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.ARCHIVE_STATUS + " INTEGER DEFAULT '0' ");
|
||||
}
|
||||
|
||||
if (oldVersion < 16 && newVersion >= 16) {
|
||||
db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE
|
||||
+ " ADD COLUMN " + LoyaltyCardDbIds.VALID_FROM + " INTEGER");
|
||||
}
|
||||
|
||||
if (oldVersion < 17 && newVersion >= 17) {
|
||||
// SQLite doesn't support modify column
|
||||
// So we need to create a temp column to change the key of the group table
|
||||
// https://www.sqlite.org/faq.html#q11
|
||||
db.beginTransaction();
|
||||
|
||||
// Step 1: Migrate LoyaltyCardDbGroups to contain integer ID
|
||||
db.execSQL("CREATE TEMPORARY TABLE tmp (" +
|
||||
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
|
||||
LoyaltyCardDbGroups.NAME + " TEXT not null," +
|
||||
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
|
||||
|
||||
db.execSQL("INSERT INTO tmp (" +
|
||||
LoyaltyCardDbGroups.NAME + " ," +
|
||||
LoyaltyCardDbGroups.ORDER + ")" +
|
||||
" SELECT " +
|
||||
LoyaltyCardDbGroups.NAME + " ," +
|
||||
LoyaltyCardDbGroups.ORDER +
|
||||
" FROM " + LoyaltyCardDbGroups.TABLE);
|
||||
|
||||
db.execSQL("DROP TABLE " + LoyaltyCardDbGroups.TABLE);
|
||||
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbGroups.TABLE + "(" +
|
||||
LoyaltyCardDbGroups.ID + " INTEGER primary key autoincrement," +
|
||||
LoyaltyCardDbGroups.NAME + " TEXT not null," +
|
||||
LoyaltyCardDbGroups.ORDER + " INTEGER DEFAULT '0')");
|
||||
|
||||
db.execSQL("INSERT INTO " + LoyaltyCardDbGroups.TABLE + "(" +
|
||||
LoyaltyCardDbGroups.ID + " ," +
|
||||
LoyaltyCardDbGroups.NAME + " ," +
|
||||
LoyaltyCardDbGroups.ORDER + ")" +
|
||||
" SELECT " +
|
||||
LoyaltyCardDbGroups.ID + " ," +
|
||||
LoyaltyCardDbGroups.NAME + " ," +
|
||||
LoyaltyCardDbGroups.ORDER +
|
||||
" FROM tmp");
|
||||
|
||||
db.execSQL("DROP TABLE tmp");
|
||||
|
||||
// Step 2: Migrate LoyaltyCardDbIdsGroups to link to ID
|
||||
db.execSQL("CREATE TEMPORARY TABLE tmp (" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
|
||||
|
||||
|
||||
db.execSQL("INSERT INTO tmp (" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " ," +
|
||||
LoyaltyCardDbIdsGroups.groupID + ")" +
|
||||
" SELECT " +
|
||||
LoyaltyCardDbGroups.NAME + " ," +
|
||||
LoyaltyCardDbGroups.ORDER +
|
||||
" FROM " + LoyaltyCardDbGroups.TABLE);
|
||||
|
||||
//////////
|
||||
db.execSQL("CREATE TABLE " + LoyaltyCardDbIdsGroups.TABLE + "(" +
|
||||
LoyaltyCardDbIdsGroups.cardID + " INTEGER," +
|
||||
LoyaltyCardDbIdsGroups.groupID + " INTEGER," +
|
||||
"primary key (" + LoyaltyCardDbIdsGroups.cardID + "," + LoyaltyCardDbIdsGroups.groupID + "))");
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
private static ContentValues generateFTSContentValues(final int id, final String store, final String note) {
|
||||
@@ -358,16 +431,17 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
public static long insertLoyaltyCard(
|
||||
final SQLiteDatabase database, final String store, final String note, final Date expiry,
|
||||
final BigDecimal balance, final Currency balanceType, final String cardId,
|
||||
final SQLiteDatabase database, final String store, final String note, final Date validFrom,
|
||||
final Date expiry, final BigDecimal balance, final Currency balanceType, final String cardId,
|
||||
final String barcodeId, final CatimaBarcode barcodeType, final Integer headerColor,
|
||||
final int starStatus, final Long lastUsed,final int archiveStatus) {
|
||||
final int starStatus, final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
// Card
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.STORE, store);
|
||||
contentValues.put(LoyaltyCardDbIds.NOTE, note);
|
||||
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
|
||||
@@ -391,9 +465,10 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
|
||||
public static long insertLoyaltyCard(
|
||||
final SQLiteDatabase database, final int id, final String store, final String note,
|
||||
final Date expiry, final BigDecimal balance, final Currency balanceType,
|
||||
final String cardId, final String barcodeId, final CatimaBarcode barcodeType,
|
||||
final Integer headerColor, final int starStatus, final Long lastUsed, final int archiveStatus) {
|
||||
final Date validFrom, final Date expiry, final BigDecimal balance,
|
||||
final Currency balanceType, final String cardId, final String barcodeId,
|
||||
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
// Card
|
||||
@@ -401,6 +476,7 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
contentValues.put(LoyaltyCardDbIds.ID, id);
|
||||
contentValues.put(LoyaltyCardDbIds.STORE, store);
|
||||
contentValues.put(LoyaltyCardDbIds.NOTE, note);
|
||||
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
|
||||
@@ -424,15 +500,17 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
|
||||
public static boolean updateLoyaltyCard(
|
||||
SQLiteDatabase database, final int id, final String store, final String note,
|
||||
final Date expiry, final BigDecimal balance, final Currency balanceType,
|
||||
final String cardId, final String barcodeId, final CatimaBarcode barcodeType,
|
||||
final Integer headerColor) {
|
||||
final Date validFrom, final Date expiry, final BigDecimal balance,
|
||||
final Currency balanceType, final String cardId, final String barcodeId,
|
||||
final CatimaBarcode barcodeType, final Integer headerColor, final int starStatus,
|
||||
final Long lastUsed, final int archiveStatus) {
|
||||
database.beginTransaction();
|
||||
|
||||
// Card
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.STORE, store);
|
||||
contentValues.put(LoyaltyCardDbIds.NOTE, note);
|
||||
contentValues.put(LoyaltyCardDbIds.VALID_FROM, validFrom != null ? validFrom.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.EXPIRY, expiry != null ? expiry.getTime() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE, balance.toString());
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE_TYPE, balanceType != null ? balanceType.getCurrencyCode() : null);
|
||||
@@ -440,6 +518,10 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_ID, barcodeId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType != null ? barcodeType.name() : null);
|
||||
contentValues.put(LoyaltyCardDbIds.HEADER_COLOR, headerColor);
|
||||
contentValues.put(LoyaltyCardDbIds.STAR_STATUS, starStatus);
|
||||
contentValues.put(LoyaltyCardDbIds.LAST_USED, lastUsed != null ? lastUsed : Utils.getUnixTime());
|
||||
contentValues.put(LoyaltyCardDbIds.ARCHIVE_STATUS, archiveStatus);
|
||||
|
||||
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
whereAttrs(LoyaltyCardDbIds.ID), withArgs(id));
|
||||
|
||||
@@ -490,6 +572,15 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public static boolean updateLoyaltyCardBalance(SQLiteDatabase database, final int id, final BigDecimal newBalance) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(LoyaltyCardDbIds.BALANCE, newBalance.toString());
|
||||
int rowsUpdated = database.update(LoyaltyCardDbIds.TABLE, contentValues,
|
||||
whereAttrs(LoyaltyCardDbIds.ID),
|
||||
withArgs(id));
|
||||
return (rowsUpdated == 1);
|
||||
}
|
||||
|
||||
public static LoyaltyCard getLoyaltyCard(SQLiteDatabase database, final int id) {
|
||||
Cursor data = database.query(LoyaltyCardDbIds.TABLE, null, whereAttrs(LoyaltyCardDbIds.ID), withArgs(id), null, null, null);
|
||||
|
||||
@@ -577,6 +668,22 @@ public class DBHelper extends SQLiteOpenHelper {
|
||||
whereAttrs(LoyaltyCardDbIds.ARCHIVE_STATUS), withArgs(1));
|
||||
}
|
||||
|
||||
public static int getArchivedCardsCount(SQLiteDatabase database, final String groupName) {
|
||||
Cursor data = database.rawQuery(
|
||||
"select * from " + LoyaltyCardDbIds.TABLE + " c " +
|
||||
" LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " cg " +
|
||||
" ON c." + LoyaltyCardDbIds.ID + " = cg." + LoyaltyCardDbIdsGroups.cardID +
|
||||
" where " + LoyaltyCardDbIds.ARCHIVE_STATUS + " = 1" +
|
||||
" AND " + LoyaltyCardDbIdsGroups.groupID + "= ?",
|
||||
withArgs(groupName)
|
||||
);
|
||||
|
||||
int count = data.getCount();
|
||||
|
||||
data.close();
|
||||
return count;
|
||||
}
|
||||
|
||||
public static Cursor getLoyaltyCardCursor(SQLiteDatabase database) {
|
||||
// An empty string will match everything
|
||||
return getLoyaltyCardCursor(database, LoyaltyCardArchiveFilter.All);
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.databinding.GroupLayoutBinding;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.GroupListItemViewHolder> {
|
||||
@@ -32,9 +35,14 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
|
||||
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.group_layout, inputParent, false);
|
||||
return new GroupListItemViewHolder(itemView);
|
||||
public GroupCursorAdapter.GroupListItemViewHolder onCreateViewHolder(@NonNull ViewGroup inputParent, int inputViewType) {
|
||||
return new GroupListItemViewHolder(
|
||||
GroupLayoutBinding.inflate(
|
||||
LayoutInflater.from(inputParent.getContext()),
|
||||
inputParent,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void onBindViewHolder(GroupListItemViewHolder inputHolder, Cursor inputCursor) {
|
||||
@@ -43,8 +51,18 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
|
||||
inputHolder.mName.setText(group._id);
|
||||
|
||||
int groupCardCount = DBHelper.getGroupCardCount(mDatabase, group._id);
|
||||
inputHolder.mCardCount.setText(mContext.getResources().getQuantityString(R.plurals.groupCardCount, groupCardCount, groupCardCount));
|
||||
int archivedCardCount = DBHelper.getArchivedCardsCount(mDatabase, group._id);
|
||||
|
||||
Resources resources = mContext.getResources();
|
||||
|
||||
String cardCountText;
|
||||
if (archivedCardCount > 0) {
|
||||
cardCountText = resources.getQuantityString(R.plurals.groupCardCountWithArchived, groupCardCount, groupCardCount, archivedCardCount);
|
||||
} else {
|
||||
cardCountText = resources.getQuantityString(R.plurals.groupCardCount, groupCardCount, groupCardCount);
|
||||
}
|
||||
|
||||
inputHolder.mCardCount.setText(cardCountText);
|
||||
inputHolder.mName.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
|
||||
inputHolder.mCardCount.setTextSize(mSettings.getFontSizeMax(mSettings.getSmallFont()));
|
||||
|
||||
@@ -70,16 +88,16 @@ public class GroupCursorAdapter extends BaseCursorAdapter<GroupCursorAdapter.Gro
|
||||
|
||||
public static class GroupListItemViewHolder extends RecyclerView.ViewHolder {
|
||||
public TextView mName, mCardCount;
|
||||
public AppCompatImageButton mMoveUp, mMoveDown, mEdit, mDelete;
|
||||
public ImageButton mMoveUp, mMoveDown, mEdit, mDelete;
|
||||
|
||||
public GroupListItemViewHolder(View inputView) {
|
||||
super(inputView);
|
||||
mName = inputView.findViewById(R.id.name);
|
||||
mCardCount = inputView.findViewById(R.id.cardCount);
|
||||
mMoveUp = inputView.findViewById(R.id.moveUp);
|
||||
mMoveDown = inputView.findViewById(R.id.moveDown);
|
||||
mEdit = inputView.findViewById(R.id.edit);
|
||||
mDelete = inputView.findViewById(R.id.delete);
|
||||
public GroupListItemViewHolder(GroupLayoutBinding groupLayoutBinding) {
|
||||
super(groupLayoutBinding.getRoot());
|
||||
mName = groupLayoutBinding.name;
|
||||
mCardCount = groupLayoutBinding.cardCount;
|
||||
mMoveUp = groupLayoutBinding.moveUp;
|
||||
mMoveDown = groupLayoutBinding.moveDown;
|
||||
mEdit = groupLayoutBinding.edit;
|
||||
mDelete = groupLayoutBinding.delete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,32 +16,33 @@ import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.databinding.ImportExportActivityBinding;
|
||||
import protect.card_locker.importexport.DataFormat;
|
||||
import protect.card_locker.importexport.ImportExportResult;
|
||||
import protect.card_locker.importexport.ImportExportResultType;
|
||||
|
||||
public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private ImportExportActivityBinding binding;
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private static final int PERMISSIONS_EXTERNAL_STORAGE = 1;
|
||||
|
||||
private ImportExportTask importExporter;
|
||||
|
||||
private String importAlertTitle;
|
||||
@@ -58,26 +59,16 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ImportExportActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.importExport);
|
||||
setContentView(R.layout.import_export_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
// If the application does not have permissions to external
|
||||
// storage, ask for it now
|
||||
|
||||
if (ContextCompat.checkSelfPermission(ImportExportActivity.this,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
|
||||
ContextCompat.checkSelfPermission(ImportExportActivity.this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(ImportExportActivity.this,
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
PERMISSIONS_EXTERNAL_STORAGE);
|
||||
Intent fileIntent = getIntent();
|
||||
if (fileIntent != null && fileIntent.getType() != null) {
|
||||
chooseImportType(false, fileIntent.getData());
|
||||
}
|
||||
|
||||
// would use ActivityResultContracts.CreateDocument() but mime type cannot be set
|
||||
@@ -129,9 +120,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
intentCreateDocumentAction.setType("application/zip");
|
||||
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "catima.zip");
|
||||
|
||||
Button exportButton = findViewById(R.id.exportButton);
|
||||
Button exportButton = binding.exportButton;
|
||||
exportButton.setOnClickListener(v -> {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(ImportExportActivity.this);
|
||||
builder.setTitle(R.string.exportPassword);
|
||||
|
||||
FrameLayout container = new FrameLayout(ImportExportActivity.this);
|
||||
@@ -161,12 +152,12 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
});
|
||||
|
||||
// Check that there is a file manager available
|
||||
Button importFilesystem = findViewById(R.id.importOptionFilesystemButton);
|
||||
importFilesystem.setOnClickListener(v -> chooseImportType(false));
|
||||
Button importFilesystem = binding.importOptionFilesystemButton;
|
||||
importFilesystem.setOnClickListener(v -> chooseImportType(false, null));
|
||||
|
||||
// Check that there is an app that data can be imported from
|
||||
Button importApplication = findViewById(R.id.importOptionApplicationButton);
|
||||
importApplication.setOnClickListener(v -> chooseImportType(true));
|
||||
Button importApplication = binding.importOptionApplicationButton;
|
||||
importApplication.setOnClickListener(v -> chooseImportType(true, null));
|
||||
}
|
||||
|
||||
private void openFileForImport(Uri uri, char[] password) {
|
||||
@@ -180,7 +171,9 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void chooseImportType(boolean choosePicker) {
|
||||
private void chooseImportType(boolean choosePicker,
|
||||
@Nullable Uri fileData) {
|
||||
|
||||
List<CharSequence> betaImportOptions = new ArrayList<>();
|
||||
betaImportOptions.add("Fidme");
|
||||
betaImportOptions.add("Stocard");
|
||||
@@ -194,7 +187,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
importOptions.add(importOption);
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(R.string.chooseImportType)
|
||||
.setItems(importOptions.toArray(new CharSequence[importOptions.size()]), (dialog, which) -> {
|
||||
switch (which) {
|
||||
@@ -232,7 +225,12 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
throw new IllegalArgumentException("Unknown DataFormat");
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
if (fileData != null) {
|
||||
openFileForImport(fileData, null);
|
||||
return;
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(importAlertTitle)
|
||||
.setMessage(importAlertMessage)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@@ -299,30 +297,6 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
mTasks.executeTask(TaskHandler.TYPE.EXPORT, importExporter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (requestCode == PERMISSIONS_EXTERNAL_STORAGE) {
|
||||
// If request is cancelled, the result arrays are empty.
|
||||
boolean success = grantResults.length > 0;
|
||||
|
||||
for (int grant : grantResults) {
|
||||
if (grant != PackageManager.PERMISSION_GRANTED) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// External storage permission rejected, inform user that
|
||||
// import/export is prevented
|
||||
Toast.makeText(getApplicationContext(), R.string.noExternalStoragePermissionError,
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mTasks.flushTaskList(TaskHandler.TYPE.IMPORT, true, false, false);
|
||||
@@ -343,7 +317,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
private void retryWithPassword(DataFormat dataFormat, Uri uri) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(R.string.passwordRequired);
|
||||
|
||||
final EditText input = new EditText(this);
|
||||
@@ -386,7 +360,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(resultType == ImportExportResultType.Success ? R.string.importSuccessfulTitle : R.string.importFailedTitle);
|
||||
builder.setMessage(buildResultDialogMessage(result, true));
|
||||
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
|
||||
@@ -397,7 +371,7 @@ public class ImportExportActivity extends CatimaAppCompatActivity {
|
||||
private void onExportComplete(ImportExportResult result, final Uri path) {
|
||||
ImportExportResultType resultType = result.resultType();
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(resultType == ImportExportResultType.Success ? R.string.exportSuccessfulTitle : R.string.exportFailedTitle);
|
||||
builder.setMessage(buildResultDialogMessage(result, false));
|
||||
builder.setNeutralButton(R.string.ok, (dialog, which) -> dialog.dismiss());
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.List;
|
||||
public class ImportURIHelper {
|
||||
private static final String STORE = DBHelper.LoyaltyCardDbIds.STORE;
|
||||
private static final String NOTE = DBHelper.LoyaltyCardDbIds.NOTE;
|
||||
private static final String VALID_FROM = DBHelper.LoyaltyCardDbIds.VALID_FROM;
|
||||
private static final String EXPIRY = DBHelper.LoyaltyCardDbIds.EXPIRY;
|
||||
private static final String BALANCE = DBHelper.LoyaltyCardDbIds.BALANCE;
|
||||
private static final String BALANCE_TYPE = DBHelper.LoyaltyCardDbIds.BALANCE_TYPE;
|
||||
@@ -62,6 +63,7 @@ public class ImportURIHelper {
|
||||
try {
|
||||
// These values are allowed to be null
|
||||
CatimaBarcode barcodeType = null;
|
||||
Date validFrom = null;
|
||||
Date expiry = null;
|
||||
BigDecimal balance = new BigDecimal("0");
|
||||
Currency balanceType = null;
|
||||
@@ -106,6 +108,10 @@ public class ImportURIHelper {
|
||||
if (unparsedBalanceType != null && !unparsedBalanceType.equals("")) {
|
||||
balanceType = Currency.getInstance(unparsedBalanceType);
|
||||
}
|
||||
String unparsedValidFrom = kv.get(VALID_FROM);
|
||||
if (unparsedValidFrom != null && !unparsedValidFrom.equals("")) {
|
||||
validFrom = new Date(Long.parseLong(unparsedValidFrom));
|
||||
}
|
||||
String unparsedExpiry = kv.get(EXPIRY);
|
||||
if (unparsedExpiry != null && !unparsedExpiry.equals("")) {
|
||||
expiry = new Date(Long.parseLong(unparsedExpiry));
|
||||
@@ -116,8 +122,8 @@ public class ImportURIHelper {
|
||||
headerColor = Integer.parseInt(unparsedHeaderColor);
|
||||
}
|
||||
|
||||
return new LoyaltyCard(-1, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100,0);
|
||||
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException ex) {
|
||||
return new LoyaltyCard(-1, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100, 0);
|
||||
} catch (NullPointerException | NumberFormatException | UnsupportedEncodingException | ArrayIndexOutOfBoundsException ex) {
|
||||
throw new InvalidObjectException("Not a valid import URI");
|
||||
}
|
||||
}
|
||||
@@ -149,6 +155,9 @@ public class ImportURIHelper {
|
||||
if (loyaltyCard.balanceType != null) {
|
||||
fragment = appendFragment(fragment, BALANCE_TYPE, loyaltyCard.balanceType.getCurrencyCode());
|
||||
}
|
||||
if (loyaltyCard.validFrom != null) {
|
||||
fragment = appendFragment(fragment, VALID_FROM, String.valueOf(loyaltyCard.validFrom.getTime()));
|
||||
}
|
||||
if (loyaltyCard.expiry != null) {
|
||||
fragment = appendFragment(fragment, EXPIRY, String.valueOf(loyaltyCard.expiry.getTime()));
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
public final int id;
|
||||
public final String store;
|
||||
public final String note;
|
||||
public final Date validFrom;
|
||||
public final Date expiry;
|
||||
public final BigDecimal balance;
|
||||
public final Currency balanceType;
|
||||
@@ -33,13 +34,16 @@ public class LoyaltyCard implements Parcelable {
|
||||
public final long lastUsed;
|
||||
public int zoomLevel;
|
||||
|
||||
public LoyaltyCard(final int id, final String store, final String note, final Date expiry,
|
||||
final BigDecimal balance, final Currency balanceType, final String cardId,
|
||||
@Nullable final String barcodeId, @Nullable final CatimaBarcode barcodeType,
|
||||
@Nullable final Integer headerColor, final int starStatus, final long lastUsed, final int zoomLevel,final int archiveStatus) {
|
||||
public LoyaltyCard(final int id, final String store, final String note, final Date validFrom,
|
||||
final Date expiry, final BigDecimal balance, final Currency balanceType,
|
||||
final String cardId, @Nullable final String barcodeId,
|
||||
@Nullable final CatimaBarcode barcodeType,
|
||||
@Nullable final Integer headerColor, final int starStatus,
|
||||
final long lastUsed, final int zoomLevel, final int archiveStatus) {
|
||||
this.id = id;
|
||||
this.store = store;
|
||||
this.note = note;
|
||||
this.validFrom = validFrom;
|
||||
this.expiry = expiry;
|
||||
this.balance = balance;
|
||||
this.balanceType = balanceType;
|
||||
@@ -57,6 +61,8 @@ public class LoyaltyCard implements Parcelable {
|
||||
id = in.readInt();
|
||||
store = in.readString();
|
||||
note = in.readString();
|
||||
long tmpValidFrom = in.readLong();
|
||||
validFrom = tmpValidFrom != -1 ? new Date(tmpValidFrom) : null;
|
||||
long tmpExpiry = in.readLong();
|
||||
expiry = tmpExpiry != -1 ? new Date(tmpExpiry) : null;
|
||||
balance = (BigDecimal) in.readValue(BigDecimal.class.getClassLoader());
|
||||
@@ -78,6 +84,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
parcel.writeInt(id);
|
||||
parcel.writeString(store);
|
||||
parcel.writeString(note);
|
||||
parcel.writeLong(validFrom != null ? validFrom.getTime() : -1);
|
||||
parcel.writeLong(expiry != null ? expiry.getTime() : -1);
|
||||
parcel.writeValue(balance);
|
||||
parcel.writeValue(balanceType);
|
||||
@@ -95,6 +102,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID));
|
||||
String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE));
|
||||
String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE));
|
||||
long validFromLong = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.VALID_FROM));
|
||||
long expiryLong = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY));
|
||||
BigDecimal balance = new BigDecimal(cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE)));
|
||||
String cardId = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID));
|
||||
@@ -110,6 +118,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
|
||||
CatimaBarcode barcodeType = null;
|
||||
Currency balanceType = null;
|
||||
Date validFrom = null;
|
||||
Date expiry = null;
|
||||
Integer headerColor = null;
|
||||
|
||||
@@ -121,6 +130,10 @@ public class LoyaltyCard implements Parcelable {
|
||||
balanceType = Currency.getInstance(cursor.getString(balanceTypeColumn));
|
||||
}
|
||||
|
||||
if (validFromLong > 0) {
|
||||
validFrom = new Date(validFromLong);
|
||||
}
|
||||
|
||||
if (expiryLong > 0) {
|
||||
expiry = new Date(expiryLong);
|
||||
}
|
||||
@@ -129,7 +142,7 @@ public class LoyaltyCard implements Parcelable {
|
||||
headerColor = cursor.getInt(headerColorColumn);
|
||||
}
|
||||
|
||||
return new LoyaltyCard(id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel,archived);
|
||||
return new LoyaltyCard(id, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starred, lastUsed, zoomLevel, archived);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,20 +16,21 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.BlendModeColorFilterCompat;
|
||||
import androidx.core.graphics.BlendModeCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
|
||||
import protect.card_locker.databinding.LoyaltyCardLayoutBinding;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder> {
|
||||
@@ -84,10 +85,15 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
return mShowDetails;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType) {
|
||||
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.loyalty_card_layout, inputParent, false);
|
||||
return new LoyaltyCardListItemViewHolder(itemView, mListener);
|
||||
public LoyaltyCardListItemViewHolder onCreateViewHolder(@NonNull ViewGroup inputParent, int inputViewType) {
|
||||
LoyaltyCardLayoutBinding loyaltyCardLayoutBinding = LoyaltyCardLayoutBinding.inflate(
|
||||
LayoutInflater.from(inputParent.getContext()),
|
||||
inputParent,
|
||||
false
|
||||
);
|
||||
return new LoyaltyCardListItemViewHolder(loyaltyCardLayoutBinding, mListener);
|
||||
}
|
||||
|
||||
public LoyaltyCard getCard(int position) {
|
||||
@@ -109,15 +115,21 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
}
|
||||
|
||||
if (mShowDetails && !loyaltyCard.balance.equals(new BigDecimal("0"))) {
|
||||
inputHolder.setBalanceField(loyaltyCard.balance, loyaltyCard.balanceType);
|
||||
inputHolder.setExtraField(inputHolder.mBalanceField, Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType), null);
|
||||
} else {
|
||||
inputHolder.setBalanceField(null, null);
|
||||
inputHolder.setExtraField(inputHolder.mBalanceField, null, null);
|
||||
}
|
||||
|
||||
if (mShowDetails && loyaltyCard.validFrom != null) {
|
||||
inputHolder.setExtraField(inputHolder.mValidFromField, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.validFrom), Utils.isNotYetValid(loyaltyCard.validFrom) ? Color.RED : null);
|
||||
} else {
|
||||
inputHolder.setExtraField(inputHolder.mValidFromField, null, null);
|
||||
}
|
||||
|
||||
if (mShowDetails && loyaltyCard.expiry != null) {
|
||||
inputHolder.setExpiryField(loyaltyCard.expiry);
|
||||
inputHolder.setExtraField(inputHolder.mExpiryField, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry), Utils.hasExpired(loyaltyCard.expiry) ? Color.RED : null);
|
||||
} else {
|
||||
inputHolder.setExpiryField(null);
|
||||
inputHolder.setExtraField(inputHolder.mExpiryField, null, null);
|
||||
}
|
||||
|
||||
setHeaderHeight(inputHolder, mShowDetails);
|
||||
@@ -170,14 +182,12 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
|
||||
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition) {
|
||||
if (itemSelected(inputPosition)) {
|
||||
inputHolder.mCardIcon.setVisibility(View.GONE);
|
||||
inputHolder.mTickIcon.setVisibility(View.VISIBLE);
|
||||
if (mCurrentSelectedIndex == inputPosition) {
|
||||
resetCurrentIndex();
|
||||
}
|
||||
} else {
|
||||
inputHolder.mTickIcon.setVisibility(View.GONE);
|
||||
inputHolder.mCardIcon.setVisibility(View.VISIBLE);
|
||||
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition) {
|
||||
resetCurrentIndex();
|
||||
}
|
||||
@@ -231,7 +241,7 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
|
||||
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
|
||||
public TextView mStoreField, mNoteField, mBalanceField, mValidFromField, mExpiryField;
|
||||
public ImageView mCardIcon, mStarBackground, mStarBorder, mTickIcon, mArchivedBackground;
|
||||
public MaterialCardView mRow, mIconLayout;
|
||||
public ConstraintLayout mStar, mArchived;
|
||||
@@ -241,22 +251,24 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
|
||||
|
||||
|
||||
protected LoyaltyCardListItemViewHolder(View inputView, CardAdapterListener inputListener) {
|
||||
super(inputView);
|
||||
mRow = inputView.findViewById(R.id.row);
|
||||
mDivider = inputView.findViewById(R.id.info_divider);
|
||||
mStoreField = inputView.findViewById(R.id.store);
|
||||
mNoteField = inputView.findViewById(R.id.note);
|
||||
mBalanceField = inputView.findViewById(R.id.balance);
|
||||
mExpiryField = inputView.findViewById(R.id.expiry);
|
||||
mIconLayout = inputView.findViewById(R.id.icon_layout);
|
||||
mCardIcon = inputView.findViewById(R.id.thumbnail);
|
||||
mStar = inputView.findViewById(R.id.star);
|
||||
mStarBackground = inputView.findViewById(R.id.star_background);
|
||||
mStarBorder = inputView.findViewById(R.id.star_border);
|
||||
mArchived = inputView.findViewById(R.id.archivedIcon);
|
||||
mArchivedBackground = inputView.findViewById(R.id.archive_background);
|
||||
mTickIcon = inputView.findViewById(R.id.selected_thumbnail);
|
||||
protected LoyaltyCardListItemViewHolder(LoyaltyCardLayoutBinding loyaltyCardLayoutBinding, CardAdapterListener inputListener) {
|
||||
super(loyaltyCardLayoutBinding.getRoot());
|
||||
View inputView = loyaltyCardLayoutBinding.getRoot();
|
||||
mRow = loyaltyCardLayoutBinding.row;
|
||||
mDivider = loyaltyCardLayoutBinding.infoDivider;
|
||||
mStoreField = loyaltyCardLayoutBinding.store;
|
||||
mNoteField = loyaltyCardLayoutBinding.note;
|
||||
mBalanceField = loyaltyCardLayoutBinding.balance;
|
||||
mValidFromField = loyaltyCardLayoutBinding.validFrom;
|
||||
mExpiryField = loyaltyCardLayoutBinding.expiry;
|
||||
mIconLayout = loyaltyCardLayoutBinding.iconLayout;
|
||||
mCardIcon = loyaltyCardLayoutBinding.thumbnail;
|
||||
mStar = loyaltyCardLayoutBinding.star;
|
||||
mStarBackground = loyaltyCardLayoutBinding.starBackground;
|
||||
mStarBorder = loyaltyCardLayoutBinding.starBorder;
|
||||
mArchived = loyaltyCardLayoutBinding.archivedIcon;
|
||||
mArchivedBackground = loyaltyCardLayoutBinding.archiveBackground;
|
||||
mTickIcon = loyaltyCardLayoutBinding.selectedThumbnail;
|
||||
inputView.setOnLongClickListener(view -> {
|
||||
inputListener.onRowClicked(getAdapterPosition());
|
||||
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
@@ -264,6 +276,41 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
});
|
||||
}
|
||||
|
||||
private void setExtraField(TextView field, String text, Integer color) {
|
||||
// If text is null, hide the field
|
||||
// If iconColor is null, use the default text and icon color based on theme
|
||||
if (text == null) {
|
||||
field.setVisibility(View.GONE);
|
||||
field.requestLayout();
|
||||
return;
|
||||
}
|
||||
|
||||
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
|
||||
|
||||
field.setVisibility(View.VISIBLE);
|
||||
field.setText(text);
|
||||
field.setTextSize(size);
|
||||
field.setTextColor(color != null ? color : MaterialColors.getColor(mContext, R.attr.colorSecondary, ContextCompat.getColor(mContext, mDarkModeEnabled ? R.color.md_theme_dark_secondary : R.color.md_theme_light_secondary)));
|
||||
|
||||
int drawableSize = dpToPx((size * 24) / 14, mContext);
|
||||
mDivider.setVisibility(View.VISIBLE);
|
||||
field.setVisibility(View.VISIBLE);
|
||||
Drawable icon = field.getCompoundDrawables()[0];
|
||||
if (icon != null) {
|
||||
icon.mutate();
|
||||
icon.setBounds(0, 0, drawableSize, drawableSize);
|
||||
field.setCompoundDrawablesRelative(icon, null, null, null);
|
||||
|
||||
if (color != null) {
|
||||
icon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_ATOP));
|
||||
} else {
|
||||
icon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(mDarkModeEnabled ? Color.WHITE : Color.BLACK, BlendModeCompat.SRC_ATOP));
|
||||
}
|
||||
}
|
||||
|
||||
field.requestLayout();
|
||||
}
|
||||
|
||||
public void setStoreField(String text) {
|
||||
mStoreField.setText(text);
|
||||
mStoreField.setTextSize(mSettings.getFontSizeMax(mSettings.getMediumFont()));
|
||||
@@ -281,49 +328,6 @@ public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCurso
|
||||
mNoteField.requestLayout();
|
||||
}
|
||||
|
||||
public void setBalanceField(BigDecimal balance, Currency balanceType) {
|
||||
if (balance == null) {
|
||||
mBalanceField.setVisibility(View.GONE);
|
||||
} else {
|
||||
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
|
||||
int drawableSize = dpToPx((size * 24) / 14, mContext);
|
||||
mDivider.setVisibility(View.VISIBLE);
|
||||
mBalanceField.setVisibility(View.VISIBLE);
|
||||
Drawable balanceIcon = mBalanceField.getCompoundDrawables()[0];
|
||||
balanceIcon.setBounds(0, 0, drawableSize, drawableSize);
|
||||
mBalanceField.setCompoundDrawablesRelative(balanceIcon, null, null, null);
|
||||
if (mDarkModeEnabled) {
|
||||
balanceIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
|
||||
}
|
||||
mBalanceField.setText(Utils.formatBalance(mContext, balance, balanceType));
|
||||
mBalanceField.setTextSize(size);
|
||||
}
|
||||
mBalanceField.requestLayout();
|
||||
}
|
||||
|
||||
public void setExpiryField(Date expiry) {
|
||||
if (expiry == null) {
|
||||
mExpiryField.setVisibility(View.GONE);
|
||||
} else {
|
||||
int size = mSettings.getFontSizeMax(mSettings.getSmallFont());
|
||||
int drawableSize = dpToPx((size * 24) / 14, mContext);
|
||||
mDivider.setVisibility(View.VISIBLE);
|
||||
mExpiryField.setVisibility(View.VISIBLE);
|
||||
Drawable expiryIcon = mExpiryField.getCompoundDrawables()[0];
|
||||
expiryIcon.setBounds(0, 0, drawableSize, drawableSize);
|
||||
mExpiryField.setCompoundDrawablesRelative(expiryIcon, null, null, null);
|
||||
if (Utils.hasExpired(expiry)) {
|
||||
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.SRC_ATOP));
|
||||
mExpiryField.setTextColor(Color.RED);
|
||||
} else if (mDarkModeEnabled) {
|
||||
expiryIcon.setColorFilter(BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.WHITE, BlendModeCompat.SRC_ATOP));
|
||||
}
|
||||
mExpiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(expiry));
|
||||
mExpiryField.setTextSize(size);
|
||||
}
|
||||
mExpiryField.requestLayout();
|
||||
}
|
||||
|
||||
public void toggleCardStateIcon(boolean enableStar, boolean enableArchive, boolean colorByTheme) {
|
||||
/* the below code does not work in android 5! hence the change of drawable instead
|
||||
boolean needDarkForeground = Utils.needsDarkForeground(mIconBackgroundColor);
|
||||
|
||||
@@ -5,10 +5,10 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
@@ -20,6 +20,7 @@ import android.os.LocaleList;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@@ -37,6 +38,7 @@ import android.widget.Toast;
|
||||
import com.google.android.material.chip.Chip;
|
||||
import com.google.android.material.chip.ChipGroup;
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@@ -51,11 +53,13 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -67,6 +71,8 @@ import java.util.concurrent.Callable;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
@@ -75,11 +81,12 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.palette.graphics.Palette;
|
||||
|
||||
import protect.card_locker.async.TaskHandler;
|
||||
import protect.card_locker.databinding.LayoutChipChoiceBinding;
|
||||
import protect.card_locker.databinding.LoyaltyCardEditActivityBinding;
|
||||
|
||||
public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
private LoyaltyCardEditActivityBinding binding;
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private final String STATE_TAB_INDEX = "savedTab";
|
||||
@@ -106,6 +113,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_FRONT = 100;
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_BACK = 101;
|
||||
private static final int PERMISSION_REQUEST_CAMERA_IMAGE_ICON = 102;
|
||||
private static final int PERMISSION_REQUEST_STORAGE_IMAGE_FRONT = 103;
|
||||
private static final int PERMISSION_REQUEST_STORAGE_IMAGE_BACK = 104;
|
||||
private static final int PERMISSION_REQUEST_STORAGE_IMAGE_ICON = 105;
|
||||
|
||||
public static final String BUNDLE_ID = "id";
|
||||
public static final String BUNDLE_DUPLICATE_ID = "duplicateId";
|
||||
@@ -118,9 +128,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
TabLayout tabs;
|
||||
|
||||
ImageView thumbnail;
|
||||
ImageView thumbnailEditIcon;
|
||||
EditText storeFieldEdit;
|
||||
EditText noteFieldEdit;
|
||||
ChipGroup groupsChips;
|
||||
AutoCompleteTextView validFromField;
|
||||
AutoCompleteTextView expiryField;
|
||||
EditText balanceField;
|
||||
AutoCompleteTextView balanceCurrencyField;
|
||||
@@ -199,6 +211,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
(int) (fieldName == LoyaltyCardField.id ? value : loyaltyCard.id),
|
||||
(String) (fieldName == LoyaltyCardField.store ? value : loyaltyCard.store),
|
||||
(String) (fieldName == LoyaltyCardField.note ? value : loyaltyCard.note),
|
||||
(Date) (fieldName == LoyaltyCardField.validFrom ? value : loyaltyCard.validFrom),
|
||||
(Date) (fieldName == LoyaltyCardField.expiry ? value : loyaltyCard.expiry),
|
||||
(BigDecimal) (fieldName == LoyaltyCardField.balance ? value : loyaltyCard.balance),
|
||||
(Currency) (fieldName == LoyaltyCardField.balanceType ? value : loyaltyCard.balanceType),
|
||||
@@ -207,7 +220,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
(CatimaBarcode) (fieldName == LoyaltyCardField.barcodeType ? value : loyaltyCard.barcodeType),
|
||||
(Integer) (fieldName == LoyaltyCardField.headerColor ? value : loyaltyCard.headerColor),
|
||||
(int) (fieldName == LoyaltyCardField.starStatus ? value : loyaltyCard.starStatus),
|
||||
Utils.getUnixTime(), 100, (int) (fieldName == LoyaltyCardField.archiveStatus ? value : loyaltyCard.archiveStatus)
|
||||
0, // Unimportant, always set to null in doSave so the DB updates it to the current timestamp
|
||||
100, // Unimportant, not updated in doSave, defaults to 100 for new cards
|
||||
(int) (fieldName == LoyaltyCardField.archiveStatus ? value : loyaltyCard.archiveStatus)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -242,7 +257,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
super.onSaveInstanceState(savedInstanceState);
|
||||
tabs = findViewById(R.id.tabs);
|
||||
tabs = binding.tabs;
|
||||
savedInstanceState.putInt(STATE_TAB_INDEX, tabs.getSelectedTabPosition());
|
||||
savedInstanceState.putParcelable(STATE_TEMP_CARD, tempLoyaltyCard);
|
||||
savedInstanceState.putInt(STATE_REQUESTED_IMAGE, mRequestedImage);
|
||||
@@ -279,7 +294,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
|
||||
tempLoyaltyCard = savedInstanceState.getParcelable(STATE_TEMP_CARD);
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
tabs = findViewById(R.id.tabs);
|
||||
tabs = binding.tabs;
|
||||
tabs.selectTab(tabs.getTabAt(savedInstanceState.getInt(STATE_TAB_INDEX)));
|
||||
mRequestedImage = savedInstanceState.getInt(STATE_REQUESTED_IMAGE);
|
||||
mFrontImageUnsaved = savedInstanceState.getInt(STATE_FRONT_IMAGE_UNSAVED) == 1;
|
||||
@@ -295,14 +310,11 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.loyalty_card_edit_activity);
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
binding = LoyaltyCardEditActivityBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
mDatabase = new DBHelper(this).getWritableDatabase();
|
||||
|
||||
@@ -314,27 +326,29 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
currencies.put(currency.getSymbol(), currency);
|
||||
}
|
||||
|
||||
tabs = findViewById(R.id.tabs);
|
||||
thumbnail = findViewById(R.id.thumbnail);
|
||||
storeFieldEdit = findViewById(R.id.storeNameEdit);
|
||||
noteFieldEdit = findViewById(R.id.noteEdit);
|
||||
groupsChips = findViewById(R.id.groupChips);
|
||||
expiryField = findViewById(R.id.expiryField);
|
||||
balanceField = findViewById(R.id.balanceField);
|
||||
balanceCurrencyField = findViewById(R.id.balanceCurrencyField);
|
||||
cardIdFieldView = findViewById(R.id.cardIdView);
|
||||
barcodeIdField = findViewById(R.id.barcodeIdField);
|
||||
barcodeTypeField = findViewById(R.id.barcodeTypeField);
|
||||
barcodeImage = findViewById(R.id.barcode);
|
||||
tabs = binding.tabs;
|
||||
thumbnail = binding.thumbnail;
|
||||
thumbnailEditIcon = binding.thumbnailEditIcon;
|
||||
storeFieldEdit = binding.storeNameEdit;
|
||||
noteFieldEdit = binding.noteEdit;
|
||||
groupsChips = binding.groupChips;
|
||||
validFromField = binding.validFromField;
|
||||
expiryField = binding.expiryField;
|
||||
balanceField = binding.balanceField;
|
||||
balanceCurrencyField = binding.balanceCurrencyField;
|
||||
cardIdFieldView = binding.cardIdView;
|
||||
barcodeIdField = binding.barcodeIdField;
|
||||
barcodeTypeField = binding.barcodeTypeField;
|
||||
barcodeImage = binding.barcode;
|
||||
barcodeImage.setClipToOutline(true);
|
||||
barcodeImageLayout = findViewById(R.id.barcodeLayout);
|
||||
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
|
||||
cardImageFrontHolder = findViewById(R.id.frontImageHolder);
|
||||
cardImageBackHolder = findViewById(R.id.backImageHolder);
|
||||
cardImageFront = findViewById(R.id.frontImage);
|
||||
cardImageBack = findViewById(R.id.backImage);
|
||||
barcodeImageLayout = binding.barcodeLayout;
|
||||
barcodeCaptureLayout = binding.barcodeCaptureLayout;
|
||||
cardImageFrontHolder = binding.frontImageHolder;
|
||||
cardImageBackHolder = binding.backImageHolder;
|
||||
cardImageFront = binding.frontImage;
|
||||
cardImageBack = binding.backImage;
|
||||
|
||||
enterButton = findViewById(R.id.enterButton);
|
||||
enterButton = binding.enterButton;
|
||||
|
||||
barcodeImageGenerationFinishedCallback = () -> {
|
||||
if (!(boolean) barcodeImage.getTag()) {
|
||||
@@ -358,38 +372,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
expiryField.addTextChangedListener(new SimpleTextWatcher() {
|
||||
CharSequence lastValue;
|
||||
addDateFieldTextChangedListener(validFromField, R.string.anyDate, R.string.chooseValidFromDate, LoyaltyCardField.validFrom);
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
lastValue = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (s.toString().equals(getString(R.string.never))) {
|
||||
expiryField.setTag(null);
|
||||
} else if (s.toString().equals(getString(R.string.chooseExpiryDate))) {
|
||||
if (!lastValue.toString().equals(getString(R.string.chooseExpiryDate))) {
|
||||
expiryField.setText(lastValue);
|
||||
}
|
||||
DialogFragment datePickerFragment = new DatePickerFragment(LoyaltyCardEditActivity.this, expiryField);
|
||||
datePickerFragment.show(getSupportFragmentManager(), "datePicker");
|
||||
}
|
||||
|
||||
updateTempState(LoyaltyCardField.expiry, expiryField.getTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
ArrayList<String> expiryList = new ArrayList<>();
|
||||
expiryList.add(0, getString(R.string.never));
|
||||
expiryList.add(1, getString(R.string.chooseExpiryDate));
|
||||
ArrayAdapter<String> expiryAdapter = new ArrayAdapter<>(LoyaltyCardEditActivity.this, android.R.layout.select_dialog_item, expiryList);
|
||||
expiryField.setAdapter(expiryAdapter);
|
||||
}
|
||||
});
|
||||
addDateFieldTextChangedListener(expiryField, R.string.never, R.string.chooseExpiryDate, LoyaltyCardField.expiry);
|
||||
|
||||
balanceField.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
@@ -401,11 +386,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
BigDecimal balance = Utils.parseCurrency(s.toString(), Utils.currencyHasDecimals(tempLoyaltyCard.balanceType));
|
||||
BigDecimal balance = Utils.parseBalance(s.toString(), tempLoyaltyCard.balanceType);
|
||||
updateTempState(LoyaltyCardField.balance, balance);
|
||||
validBalance = true;
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (ParseException e) {
|
||||
validBalance = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -507,7 +491,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
barcodeIdField.setText(lastValue);
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(LoyaltyCardEditActivity.this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(LoyaltyCardEditActivity.this);
|
||||
builder.setTitle(R.string.setBarcodeId);
|
||||
final EditText input = new EditText(LoyaltyCardEditActivity.this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
@@ -771,7 +755,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
} else {
|
||||
// New card, use default values
|
||||
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(), 100,0);
|
||||
tempLoyaltyCard = new LoyaltyCard(-1, "", "", null, null, new BigDecimal("0"), null, "", null, null, null, 0, Utils.getUnixTime(), 100,0);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -814,7 +798,8 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
storeFieldEdit.setText(tempLoyaltyCard.store);
|
||||
noteFieldEdit.setText(tempLoyaltyCard.note);
|
||||
formatExpiryField(this, expiryField, tempLoyaltyCard.expiry);
|
||||
formatDateField(this, validFromField, tempLoyaltyCard.validFrom);
|
||||
formatDateField(this, expiryField, tempLoyaltyCard.expiry);
|
||||
formatBalanceCurrencyField(tempLoyaltyCard.balanceType);
|
||||
cardIdFieldView.setText(tempLoyaltyCard.cardId);
|
||||
barcodeIdField.setText(tempLoyaltyCard.barcodeId != null ? tempLoyaltyCard.barcodeId : getString(R.string.sameAsCardId));
|
||||
@@ -832,7 +817,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
for (Group group : DBHelper.getGroups(mDatabase)) {
|
||||
Chip chip = (Chip) getLayoutInflater().inflate(R.layout.layout_chip_choice, groupsChips, false);
|
||||
LayoutChipChoiceBinding chipChoiceBinding = LayoutChipChoiceBinding
|
||||
.inflate(LayoutInflater.from(groupsChips.getContext()), groupsChips, false);
|
||||
Chip chip = chipChoiceBinding.getRoot();
|
||||
chip.setText(group._id);
|
||||
chip.setTag(group);
|
||||
|
||||
@@ -864,12 +851,6 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
updateTempState(LoyaltyCardField.headerColor, Utils.getRandomHeaderColor(this));
|
||||
}
|
||||
|
||||
// It can't be null because we set it in updateTempState but SpotBugs insists it can be
|
||||
// NP_NULL_ON_SOME_PATH: Possible null pointer dereference
|
||||
if (tempLoyaltyCard.headerColor != null) {
|
||||
thumbnail.setOnClickListener(new ChooseCardImage());
|
||||
}
|
||||
|
||||
// Update from intent
|
||||
if (barcodeType != null) {
|
||||
try {
|
||||
@@ -910,19 +891,34 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
cardImageFrontHolder.setOnClickListener(new ChooseCardImage());
|
||||
cardImageBackHolder.setOnClickListener(new ChooseCardImage());
|
||||
|
||||
FloatingActionButton saveButton = findViewById(R.id.fabSave);
|
||||
FloatingActionButton saveButton = binding.fabSave;
|
||||
saveButton.setOnClickListener(v -> doSave());
|
||||
saveButton.bringToFront();
|
||||
|
||||
generateIcon(storeFieldEdit.getText().toString());
|
||||
|
||||
// It can't be null because we set it in updateTempState but SpotBugs insists it can be
|
||||
// NP_NULL_ON_SOME_PATH: Possible null pointer dereference and
|
||||
// NP_NULL_PARAM_DEREF: Method call passes null for non-null parameter
|
||||
Integer headerColor = tempLoyaltyCard.headerColor;
|
||||
if (headerColor != null) {
|
||||
thumbnail.setOnClickListener(new ChooseCardImage());
|
||||
thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(headerColor) ? Color.BLACK : Color.WHITE);
|
||||
thumbnailEditIcon.setColorFilter(Utils.needsDarkForeground(headerColor) ? Color.WHITE : Color.BLACK);
|
||||
}
|
||||
|
||||
onResuming = false;
|
||||
}
|
||||
|
||||
protected void setColorFromIcon() {
|
||||
Object icon = thumbnail.getTag();
|
||||
if (icon != null && (icon instanceof Bitmap)) {
|
||||
updateTempState(LoyaltyCardField.headerColor, Utils.getHeaderColorFromImage((Bitmap) icon, tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : R.attr.colorPrimary));
|
||||
int headerColor = Utils.getHeaderColorFromImage((Bitmap) icon, tempLoyaltyCard.headerColor != null ? tempLoyaltyCard.headerColor : R.attr.colorPrimary);
|
||||
|
||||
updateTempState(LoyaltyCardField.headerColor, headerColor);
|
||||
|
||||
thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(headerColor) ? Color.BLACK : Color.WHITE);
|
||||
thumbnailEditIcon.setColorFilter(Utils.needsDarkForeground(headerColor) ? Color.WHITE : Color.BLACK);
|
||||
} else {
|
||||
Log.d("setColorFromIcon", "attempting header color change from icon but icon does not exist");
|
||||
}
|
||||
@@ -938,13 +934,62 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
protected static void formatExpiryField(Context context, EditText expiryField, Date expiry) {
|
||||
expiryField.setTag(expiry);
|
||||
protected void addDateFieldTextChangedListener(AutoCompleteTextView dateField, @StringRes int defaultOptionStringId, @StringRes int chooseDateOptionStringId, LoyaltyCardField loyaltyCardField) {
|
||||
dateField.addTextChangedListener(new SimpleTextWatcher() {
|
||||
CharSequence lastValue;
|
||||
|
||||
if (expiry == null) {
|
||||
expiryField.setText(context.getString(R.string.never));
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
lastValue = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (s.toString().equals(getString(defaultOptionStringId))) {
|
||||
dateField.setTag(null);
|
||||
} else if (s.toString().equals(getString(chooseDateOptionStringId))) {
|
||||
if (!lastValue.toString().equals(getString(chooseDateOptionStringId))) {
|
||||
dateField.setText(lastValue);
|
||||
}
|
||||
DialogFragment datePickerFragment = new DatePickerFragment(
|
||||
LoyaltyCardEditActivity.this,
|
||||
dateField,
|
||||
// if the expiry date is being set, set date picker's minDate to the 'valid from' date
|
||||
loyaltyCardField == LoyaltyCardField.expiry ? (Date) validFromField.getTag() : null,
|
||||
// if the 'valid from' date is being set, set date picker's maxDate to the expiry date
|
||||
loyaltyCardField == LoyaltyCardField.validFrom ? (Date) expiryField.getTag() : null);
|
||||
datePickerFragment.show(getSupportFragmentManager(), "datePicker");
|
||||
}
|
||||
|
||||
updateTempState(loyaltyCardField, dateField.getTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
ArrayList<String> dropdownOptions = new ArrayList<>();
|
||||
dropdownOptions.add(0, getString(defaultOptionStringId));
|
||||
dropdownOptions.add(1, getString(chooseDateOptionStringId));
|
||||
ArrayAdapter<String> dropdownOptionsAdapter = new ArrayAdapter<>(LoyaltyCardEditActivity.this, android.R.layout.select_dialog_item, dropdownOptions);
|
||||
dateField.setAdapter(dropdownOptionsAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static void formatDateField(Context context, EditText textField, Date date) {
|
||||
textField.setTag(date);
|
||||
|
||||
if (date == null) {
|
||||
String text;
|
||||
if (textField.getId() == R.id.validFromField) {
|
||||
text = context.getString(R.string.anyDate);
|
||||
} else if (textField.getId() == R.id.expiryField) {
|
||||
text = context.getString(R.string.never);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown textField Id " + textField.getId());
|
||||
}
|
||||
textField.setText(text);
|
||||
} else {
|
||||
expiryField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(expiry));
|
||||
textField.setText(DateFormat.getDateInstance(DateFormat.LONG).format(date));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -965,18 +1010,59 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
try {
|
||||
if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_FRONT) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_FRONT);
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_BACK) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_BACK);
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_ICON) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_ICON);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
onMockedRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||
Integer failureReason = null;
|
||||
|
||||
if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_FRONT) {
|
||||
if (granted) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_FRONT);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.cameraPermissionRequired;
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_BACK) {
|
||||
if (granted) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_BACK);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.cameraPermissionRequired;
|
||||
} else if (requestCode == PERMISSION_REQUEST_CAMERA_IMAGE_ICON) {
|
||||
if (granted) {
|
||||
takePhotoForCard(Utils.CARD_IMAGE_FROM_CAMERA_ICON);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.cameraPermissionRequired;
|
||||
} else if (requestCode == PERMISSION_REQUEST_STORAGE_IMAGE_FRONT) {
|
||||
if (granted) {
|
||||
selectImageFromGallery(Utils.CARD_IMAGE_FROM_FILE_FRONT);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.storageReadPermissionRequired;
|
||||
} else if (requestCode == PERMISSION_REQUEST_STORAGE_IMAGE_BACK) {
|
||||
if (granted) {
|
||||
selectImageFromGallery(Utils.CARD_IMAGE_FROM_FILE_BACK);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.storageReadPermissionRequired;
|
||||
} else if (requestCode == PERMISSION_REQUEST_STORAGE_IMAGE_ICON) {
|
||||
if (granted) {
|
||||
selectImageFromGallery(Utils.CARD_IMAGE_FROM_FILE_ICON);
|
||||
return;
|
||||
}
|
||||
|
||||
failureReason = R.string.storageReadPermissionRequired;
|
||||
}
|
||||
|
||||
if (failureReason != null) {
|
||||
Toast.makeText(this, failureReason, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -993,7 +1079,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
new MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.updateBarcodeQuestionTitle)
|
||||
.setMessage(R.string.updateBarcodeQuestionText)
|
||||
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||
@@ -1027,7 +1113,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
if (confirmExitDialog == null) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(R.string.leaveWithoutSaveTitle);
|
||||
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
|
||||
builder.setPositiveButton(R.string.confirm, (dialog, which) -> {
|
||||
@@ -1048,6 +1134,24 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
mPhotoTakerLauncher.launch(photoURI);
|
||||
}
|
||||
|
||||
private void selectImageFromGallery(int type) {
|
||||
mRequestedImage = type;
|
||||
|
||||
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
|
||||
photoPickerIntent.setType("image/*");
|
||||
Intent contentIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
contentIntent.setType("image/*");
|
||||
Intent chooserIntent = Intent.createChooser(photoPickerIntent, getString(R.string.addFromImage));
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { contentIntent });
|
||||
|
||||
try {
|
||||
mPhotoPickerLauncher.launch(chooserIntent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedLaunchingPhotoPicker, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
|
||||
class EditCardIdAndBarcode implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -1104,6 +1208,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
public void onColorSelected(int dialogId, int color) {
|
||||
updateTempState(LoyaltyCardField.headerColor, color);
|
||||
|
||||
thumbnailEditIcon.setBackgroundColor(Utils.needsDarkForeground(color) ? Color.BLACK : Color.WHITE);
|
||||
thumbnailEditIcon.setColorFilter(Utils.needsDarkForeground(color) ? Color.WHITE : Color.BLACK);
|
||||
|
||||
// Unset image if set
|
||||
thumbnail.setTag(null);
|
||||
|
||||
@@ -1126,52 +1233,38 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
cardOptions.put(getString(R.string.takePhoto), () -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int permissionRequestType;
|
||||
int permissionRequestType;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
requestPermissions(new String[]{Manifest.permission.CAMERA}, permissionRequestType);
|
||||
} else {
|
||||
int cardImageType;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
cardImageType = Utils.CARD_IMAGE_FROM_CAMERA_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
takePhotoForCard(cardImageType);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
cardOptions.put(getString(R.string.addFromImage), () -> {
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_FRONT;
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_BACK;
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
mRequestedImage = Utils.CARD_IMAGE_FROM_FILE_ICON;
|
||||
permissionRequestType = PERMISSION_REQUEST_CAMERA_IMAGE_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
Intent i = new Intent(Intent.ACTION_PICK);
|
||||
i.setType("image/*");
|
||||
mPhotoPickerLauncher.launch(i);
|
||||
PermissionUtils.requestCameraPermission(LoyaltyCardEditActivity.this, permissionRequestType);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
cardOptions.put(getString(R.string.addFromImage), () -> {
|
||||
int permissionRequestType;
|
||||
|
||||
if (v.getId() == R.id.frontImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_STORAGE_IMAGE_FRONT;
|
||||
} else if (v.getId() == R.id.backImageHolder) {
|
||||
permissionRequestType = PERMISSION_REQUEST_STORAGE_IMAGE_BACK;
|
||||
} else if (v.getId() == R.id.thumbnail) {
|
||||
permissionRequestType = PERMISSION_REQUEST_STORAGE_IMAGE_ICON;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
PermissionUtils.requestStorageReadPermission(LoyaltyCardEditActivity.this, permissionRequestType);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -1187,7 +1280,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
throw new IllegalArgumentException("Unknown ID type " + v.getId());
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(LoyaltyCardEditActivity.this)
|
||||
new MaterialAlertDialogBuilder(LoyaltyCardEditActivity.this)
|
||||
.setTitle(getString(titleResource))
|
||||
.setItems(cardOptions.keySet().toArray(new CharSequence[cardOptions.size()]), (dialog, which) -> {
|
||||
Iterator<Callable<Void>> callables = cardOptions.values().iterator();
|
||||
@@ -1201,6 +1294,10 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
callable.call();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
// Rethrow as NoSuchElementException
|
||||
// This isn't really true, but a View.OnClickListener doesn't allow throwing other types
|
||||
throw new NoSuchElementException(e.getMessage());
|
||||
}
|
||||
})
|
||||
.show();
|
||||
@@ -1211,11 +1308,17 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
implements DatePickerDialog.OnDateSetListener {
|
||||
|
||||
final Context context;
|
||||
final EditText expiryFieldEdit;
|
||||
final EditText textFieldEdit;
|
||||
@Nullable
|
||||
final Date minDate;
|
||||
@Nullable
|
||||
final Date maxDate;
|
||||
|
||||
DatePickerFragment(Context context, EditText expiryFieldEdit) {
|
||||
DatePickerFragment(Context context, EditText textFieldEdit, @Nullable Date minDate, @Nullable Date maxDate) {
|
||||
this.context = context;
|
||||
this.expiryFieldEdit = expiryFieldEdit;
|
||||
this.textFieldEdit = textFieldEdit;
|
||||
this.minDate = minDate;
|
||||
this.maxDate = maxDate;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -1224,7 +1327,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
// Use the current date as the default date in the picker
|
||||
final Calendar c = Calendar.getInstance();
|
||||
|
||||
Date date = (Date) expiryFieldEdit.getTag();
|
||||
Date date = (Date) textFieldEdit.getTag();
|
||||
if (date != null) {
|
||||
c.setTime(date);
|
||||
}
|
||||
@@ -1235,23 +1338,29 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
// Create a new instance of DatePickerDialog and return it
|
||||
DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(), this, year, month, day);
|
||||
datePickerDialog.getDatePicker().setMinDate(getMinDateOfDatePicker());
|
||||
datePickerDialog.getDatePicker().setMinDate(minDate != null ? minDate.getTime() : getDefaultMinDateOfDatePicker());
|
||||
datePickerDialog.getDatePicker().setMaxDate(maxDate != null ? maxDate.getTime() : getDefaultMaxDateOfDatePicker());
|
||||
return datePickerDialog;
|
||||
}
|
||||
|
||||
private long getMinDateOfDatePicker()
|
||||
{
|
||||
private long getDefaultMinDateOfDatePicker() {
|
||||
Calendar minDateCalendar = Calendar.getInstance();
|
||||
minDateCalendar.set(1970, 0, 1);
|
||||
return minDateCalendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
private long getDefaultMaxDateOfDatePicker() {
|
||||
Calendar maxDateCalendar = Calendar.getInstance();
|
||||
maxDateCalendar.set(2100, 11, 31);
|
||||
return maxDateCalendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
public void onDateSet(DatePicker view, int year, int month, int day) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.set(Calendar.YEAR, year);
|
||||
c.set(Calendar.MONTH, month);
|
||||
c.set(Calendar.DAY_OF_MONTH, day);
|
||||
c.set(Calendar.HOUR, 0);
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
@@ -1260,7 +1369,7 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
|
||||
Date date = new Date(unixTime);
|
||||
|
||||
formatExpiryField(context, expiryFieldEdit, date);
|
||||
formatDateField(context, textFieldEdit, date);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1297,35 +1406,34 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
selectedGroups.add((Group) chip.getTag());
|
||||
}
|
||||
|
||||
if (updateLoyaltyCard) { //update of "starStatus" not necessary, since it cannot be changed in this activity (only in ViewActivity)
|
||||
DBHelper.updateLoyaltyCard(mDatabase, loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor);
|
||||
try {
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(this, (Bitmap) thumbnail.getTag(), loyaltyCardId, ImageLocationType.icon);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.i(TAG, "Updated " + loyaltyCardId + " to " + cardId);
|
||||
// Both update and new card save with lastUsed set to null
|
||||
// This makes the DBHelper set it to the current date
|
||||
// So that new and edited card are always on top when sorting by recently used
|
||||
if (updateLoyaltyCard) {
|
||||
DBHelper.updateLoyaltyCard(mDatabase, loyaltyCardId, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, tempLoyaltyCard.starStatus, null, tempLoyaltyCard.archiveStatus);
|
||||
} else {
|
||||
loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, tempLoyaltyCard.lastUsed,0);
|
||||
try {
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(this, (Bitmap) thumbnail.getTag(), loyaltyCardId, ImageLocationType.icon);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, tempLoyaltyCard.store, tempLoyaltyCard.note, tempLoyaltyCard.validFrom, tempLoyaltyCard.expiry, tempLoyaltyCard.balance, tempLoyaltyCard.balanceType, tempLoyaltyCard.cardId, tempLoyaltyCard.barcodeId, tempLoyaltyCard.barcodeType, tempLoyaltyCard.headerColor, 0, null, 0);
|
||||
}
|
||||
|
||||
try {
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageFront.getTag(), loyaltyCardId, ImageLocationType.front);
|
||||
Utils.saveCardImage(this, (Bitmap) cardImageBack.getTag(), loyaltyCardId, ImageLocationType.back);
|
||||
Utils.saveCardImage(this, (Bitmap) thumbnail.getTag(), loyaltyCardId, ImageLocationType.icon);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Log.i(TAG, "Set " + loyaltyCardId + " to " + cardId + " (update: " + updateLoyaltyCard + ")");
|
||||
|
||||
DBHelper.setLoyaltyCardGroups(mDatabase, loyaltyCardId, selectedGroups);
|
||||
|
||||
ShortcutHelper.updateShortcuts(this, DBHelper.getLoyaltyCard(mDatabase, loyaltyCardId));
|
||||
|
||||
if(duplicateFromLoyaltyCardId){
|
||||
if (duplicateFromLoyaltyCardId) {
|
||||
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -1478,9 +1586,9 @@ public class LoyaltyCardEditActivity extends CatimaAppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
View cardPart = findViewById(R.id.cardPart);
|
||||
View optionsPart = findViewById(R.id.optionsPart);
|
||||
View picturesPart = findViewById(R.id.picturesPart);
|
||||
View cardPart = binding.cardPart;
|
||||
View optionsPart = binding.optionsPart;
|
||||
View picturesPart = binding.picturesPart;
|
||||
|
||||
if (getString(R.string.card).equals(part)) {
|
||||
cardPart.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -4,6 +4,7 @@ public enum LoyaltyCardField {
|
||||
id,
|
||||
store,
|
||||
note,
|
||||
validFrom,
|
||||
expiry,
|
||||
balance,
|
||||
balanceType,
|
||||
|
||||
@@ -3,9 +3,6 @@ package protect.card_locker;
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import com.google.android.material.color.DynamicColors;
|
||||
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class LoyaltyCardLockerApplication extends Application {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,9 +9,14 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.CursorIndexOutOfBoundsException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
@@ -25,24 +30,35 @@ import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.view.ActionMode;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.splashscreen.SplashScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import protect.card_locker.databinding.ArchiveActivityBinding;
|
||||
import protect.card_locker.databinding.ContentMainBinding;
|
||||
import protect.card_locker.databinding.MainActivityBinding;
|
||||
import protect.card_locker.databinding.SortingOptionBinding;
|
||||
import protect.card_locker.preferences.SettingsActivity;
|
||||
|
||||
public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCardCursorAdapter.CardAdapterListener, GestureDetector.OnGestureListener {
|
||||
private MainActivityBinding binding;
|
||||
private ArchiveActivityBinding archiveActivityBinding;
|
||||
private ContentMainBinding contentMainBinding;
|
||||
private static final String TAG = "Catima";
|
||||
public static final String RESTART_ACTIVITY_INTENT = "restart_activity_intent";
|
||||
|
||||
private static final int MEDIUM_SCALE_FACTOR_DIP = 460;
|
||||
|
||||
private SQLiteDatabase mDatabase;
|
||||
private LoyaltyCardCursorAdapter mAdapter;
|
||||
private ActionMode mCurrentActionMode;
|
||||
@@ -55,9 +71,10 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
protected DBHelper.LoyaltyCardOrderDirection mOrderDirection = DBHelper.LoyaltyCardOrderDirection.Ascending;
|
||||
protected int selectedTab = 0;
|
||||
private RecyclerView mCardList;
|
||||
private View mHelpText;
|
||||
private View mHelpSection;
|
||||
private View mNoMatchingCardsText;
|
||||
private View mNoGroupCardsText;
|
||||
private TabLayout groupsTabLayout;
|
||||
|
||||
private boolean mArchiveMode;
|
||||
public static final String BUNDLE_ARCHIVE_MODE = "archiveMode";
|
||||
@@ -131,7 +148,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
inputMode.finish();
|
||||
return true;
|
||||
} else if (inputItem.getItemId() == R.id.action_delete) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(MainActivity.this);
|
||||
// The following may seem weird, but it is necessary to give translators enough flexibility.
|
||||
// For example, in Russian, Android's plural quantity "one" actually refers to "any number ending on 1 but not ending in 11".
|
||||
// So while in English the extra non-plural form seems unnecessary duplication, it is necessary to give translators enough flexibility.
|
||||
@@ -153,7 +170,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
ShortcutHelper.removeShortcut(MainActivity.this, loyaltyCard.id);
|
||||
}
|
||||
|
||||
TabLayout.Tab tab = ((TabLayout) findViewById(R.id.groups)).getTabAt(selectedTab);
|
||||
TabLayout.Tab tab = groupsTabLayout.getTabAt(selectedTab);
|
||||
mGroup = tab != null ? tab.getTag() : null;
|
||||
|
||||
updateLoyaltyCardList(true);
|
||||
@@ -165,28 +182,25 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
dialog.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(inputItem.getItemId() == R.id.action_archive){
|
||||
} else if (inputItem.getItemId() == R.id.action_archive) {
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.d(TAG, "Archiving card: " + loyaltyCard.id);
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id,1);
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id, 1);
|
||||
updateLoyaltyCardList(false);
|
||||
inputMode.finish();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(inputItem.getItemId() == R.id.action_unarchive){
|
||||
} else if (inputItem.getItemId() == R.id.action_unarchive) {
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.d(TAG, "Unarchiving card: " + loyaltyCard.id);
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id,0);
|
||||
DBHelper.updateLoyaltyCardArchiveStatus(mDatabase, loyaltyCard.id, 0);
|
||||
updateLoyaltyCardList(false);
|
||||
inputMode.finish();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(inputItem.getItemId() == R.id.action_star){
|
||||
} else if (inputItem.getItemId() == R.id.action_star) {
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.d(TAG, "Starring card: " + loyaltyCard.id);
|
||||
DBHelper.updateLoyaltyCardStarStatus(mDatabase, loyaltyCard.id, 1);
|
||||
@@ -194,8 +208,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
inputMode.finish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(inputItem.getItemId() == R.id.action_unstar){
|
||||
} else if (inputItem.getItemId() == R.id.action_unstar) {
|
||||
for (LoyaltyCard loyaltyCard : mAdapter.getSelectedItems()) {
|
||||
Log.d(TAG, "Unstarring card: " + loyaltyCard.id);
|
||||
DBHelper.updateLoyaltyCardStarStatus(mDatabase, loyaltyCard.id, 0);
|
||||
@@ -218,33 +231,30 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
@Override
|
||||
protected void onCreate(Bundle inputSavedInstanceState) {
|
||||
extractIntentFields(getIntent());
|
||||
super.onCreate(inputSavedInstanceState);
|
||||
SplashScreen.installSplashScreen(this);
|
||||
if(!mArchiveMode) {
|
||||
super.onCreate(inputSavedInstanceState);
|
||||
if (!mArchiveMode) {
|
||||
binding = MainActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.app_name);
|
||||
setContentView(R.layout.main_activity);
|
||||
}
|
||||
else{
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
groupsTabLayout = binding.groups;
|
||||
contentMainBinding = ContentMainBinding.bind(binding.include.getRoot());
|
||||
} else {
|
||||
archiveActivityBinding = ArchiveActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.archiveList);
|
||||
setContentView(R.layout.archive_activity);
|
||||
setContentView(archiveActivityBinding.getRoot());
|
||||
setSupportActionBar(archiveActivityBinding.toolbar);
|
||||
groupsTabLayout = archiveActivityBinding.groups;
|
||||
contentMainBinding = ContentMainBinding.bind(archiveActivityBinding.include.getRoot());
|
||||
}
|
||||
// XXX color patching has to be done again after setting splash screen
|
||||
Utils.patchColors(this);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if(mArchiveMode){
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
if(mArchiveMode) {
|
||||
enableToolbarBackButton();
|
||||
}
|
||||
|
||||
mDatabase = new DBHelper(this).getWritableDatabase();
|
||||
|
||||
|
||||
|
||||
TabLayout groupsTabLayout = findViewById(R.id.groups);
|
||||
groupsTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
@@ -276,12 +286,11 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
View.OnTouchListener gestureTouchListener = (v, event) -> mGestureDetector.onTouchEvent(event);
|
||||
|
||||
mHelpText = findViewById(R.id.helpText);
|
||||
mNoMatchingCardsText = findViewById(R.id.noMatchingCardsText);
|
||||
mNoGroupCardsText = findViewById(R.id.noGroupCardsText);
|
||||
mCardList = findViewById(R.id.list);
|
||||
mHelpSection = contentMainBinding.helpSection;
|
||||
mNoMatchingCardsText = contentMainBinding.noMatchingCardsText;
|
||||
mNoGroupCardsText = contentMainBinding.noGroupCardsText;
|
||||
mCardList = contentMainBinding.list;
|
||||
|
||||
mHelpText.setOnTouchListener(gestureTouchListener);
|
||||
mNoMatchingCardsText.setOnTouchListener(gestureTouchListener);
|
||||
mCardList.setOnTouchListener(gestureTouchListener);
|
||||
mNoGroupCardsText.setOnTouchListener(gestureTouchListener);
|
||||
@@ -325,21 +334,17 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
*/
|
||||
|
||||
mBarcodeScannerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
// Exit early if the user cancelled the scan (pressed back/home)
|
||||
if (result.getResultCode() != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = result.getData();
|
||||
BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(Utils.BARCODE_SCAN, result.getResultCode(), intent, this);
|
||||
|
||||
if (!barcodeValues.isEmpty()) {
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
if (inputBundle != null && inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP));
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
Bundle inputBundle = intent.getExtras();
|
||||
String group = inputBundle != null ? inputBundle.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) : null;
|
||||
processBarcodeValues(barcodeValues, group);
|
||||
});
|
||||
|
||||
mSettingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
@@ -368,7 +373,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
|
||||
// Start of active tab logic
|
||||
TabLayout groupsTabLayout = findViewById(R.id.groups);
|
||||
updateTabGroups(groupsTabLayout);
|
||||
|
||||
// Restore settings from Shared Preference
|
||||
@@ -396,12 +400,15 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
groupsTabLayout.selectTab(tab);
|
||||
assert tab != null;
|
||||
mGroup = tab.getTag();
|
||||
} else if (!mArchiveMode) {
|
||||
scaleScreen();
|
||||
}
|
||||
|
||||
updateLoyaltyCardList(true);
|
||||
// End of active tab logic
|
||||
|
||||
if (!mArchiveMode) {
|
||||
FloatingActionButton addButton = findViewById(R.id.fabAdd);
|
||||
FloatingActionButton addButton = binding.fabAdd;
|
||||
|
||||
addButton.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(getApplicationContext(), ScanActivity.class);
|
||||
@@ -418,8 +425,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
|
||||
if (!mSearchView.isIconified()) {
|
||||
if (mSearchView != null && !mSearchView.isIconified()) {
|
||||
mSearchView.setIconified(true);
|
||||
return;
|
||||
}
|
||||
@@ -455,7 +461,7 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
// We want the cardList to be visible regardless of the filtered match count
|
||||
// to ensure that the noMatchingCardsText doesn't end up being shown below
|
||||
// the keyboard
|
||||
mHelpText.setVisibility(View.GONE);
|
||||
mHelpSection.setVisibility(View.GONE);
|
||||
mNoGroupCardsText.setVisibility(View.GONE);
|
||||
|
||||
if (mAdapter.getItemCount() > 0) {
|
||||
@@ -474,8 +480,14 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mArchiveMode) {
|
||||
// If an user deletes the last card in archive mode, we should close the activity
|
||||
// This will move us back to the main view
|
||||
finish();
|
||||
}
|
||||
|
||||
mCardList.setVisibility(View.GONE);
|
||||
mHelpText.setVisibility(View.VISIBLE);
|
||||
mHelpSection.setVisibility(View.VISIBLE);
|
||||
|
||||
mNoMatchingCardsText.setVisibility(View.GONE);
|
||||
mNoGroupCardsText.setVisibility(View.GONE);
|
||||
@@ -486,9 +498,67 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
}
|
||||
|
||||
private void processBarcodeValues(BarcodeValues barcodeValues, String group) {
|
||||
if (barcodeValues.isEmpty()) {
|
||||
throw new IllegalArgumentException("barcodesValues may not be empty");
|
||||
}
|
||||
|
||||
Intent newIntent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
|
||||
Bundle newBundle = new Bundle();
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_BARCODETYPE, barcodeValues.format());
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_CARDID, barcodeValues.content());
|
||||
if (group != null) {
|
||||
newBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, group);
|
||||
}
|
||||
newIntent.putExtras(newBundle);
|
||||
startActivity(newIntent);
|
||||
}
|
||||
|
||||
private void onSharedIntent(Intent intent) {
|
||||
String receivedAction = intent.getAction();
|
||||
String receivedType = intent.getType();
|
||||
|
||||
// Check if an image was shared to us
|
||||
if (Intent.ACTION_SEND.equals(receivedAction)) {
|
||||
if (receivedType.startsWith("image/")) {
|
||||
BarcodeValues barcodeValues;
|
||||
try {
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
Uri data = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
bitmap = Utils.retrieveImageFromUri(this, data);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error getting data from image file");
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
barcodeValues = Utils.getBarcodeFromBitmap(bitmap);
|
||||
|
||||
if (barcodeValues.isEmpty()) {
|
||||
Log.i(TAG, "No barcode found in image file");
|
||||
Toast.makeText(this, R.string.noBarcodeFound, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
processBarcodeValues(barcodeValues, null);
|
||||
} else {
|
||||
Log.e(TAG, "Wrong mime-type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractIntentFields(Intent intent) {
|
||||
final Bundle b = intent.getExtras();
|
||||
mArchiveMode = b != null && b.getBoolean(BUNDLE_ARCHIVE_MODE, false);
|
||||
onSharedIntent(intent);
|
||||
}
|
||||
|
||||
public void updateTabGroups(TabLayout groupsTabLayout) {
|
||||
@@ -520,9 +590,9 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu inputMenu) {
|
||||
if(!mArchiveMode)
|
||||
if (!mArchiveMode) {
|
||||
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
|
||||
else{
|
||||
} else {
|
||||
getMenuInflater().inflate(R.menu.archive_menu, inputMenu);
|
||||
}
|
||||
|
||||
@@ -550,7 +620,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
mFilter = newText;
|
||||
|
||||
TabLayout groupsTabLayout = findViewById(R.id.groups);
|
||||
TabLayout.Tab currentTab = groupsTabLayout.getTabAt(groupsTabLayout.getSelectedTabPosition());
|
||||
mGroup = currentTab != null ? currentTab.getTag() : null;
|
||||
|
||||
@@ -560,7 +629,8 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
});
|
||||
}
|
||||
if(!mArchiveMode) {
|
||||
|
||||
if (!mArchiveMode) {
|
||||
if (DBHelper.getArchivedCardsCount(mDatabase) == 0) {
|
||||
inputMenu.findItem(R.id.action_archived).setVisible(false);
|
||||
} else {
|
||||
@@ -596,13 +666,15 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(MainActivity.this);
|
||||
builder.setTitle(R.string.sort_by);
|
||||
|
||||
final View customLayout = getLayoutInflater().inflate(R.layout.sorting_option, null);
|
||||
SortingOptionBinding sortingOptionBinding = SortingOptionBinding
|
||||
.inflate(LayoutInflater.from(MainActivity.this), null, false);
|
||||
final View customLayout = sortingOptionBinding.getRoot();
|
||||
builder.setView(customLayout);
|
||||
|
||||
CheckBox showReversed = (CheckBox) customLayout.findViewById(R.id.checkBox_reverse);
|
||||
CheckBox showReversed = sortingOptionBinding.checkBoxReverse;
|
||||
|
||||
|
||||
showReversed.setChecked(mOrderDirection == DBHelper.LoyaltyCardOrderDirection.Descending);
|
||||
@@ -634,6 +706,15 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_archived) {
|
||||
Intent i = new Intent(getApplicationContext(), MainActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean("archiveMode", true);
|
||||
i.putExtras(bundle);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == R.id.action_import_export) {
|
||||
Intent i = new Intent(getApplicationContext(), ImportExportActivity.class);
|
||||
startActivity(i);
|
||||
@@ -652,15 +733,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == R.id.action_archived){
|
||||
Intent i = new Intent(getApplicationContext(), MainActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean("archiveMode", true);
|
||||
i.putExtras(bundle);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return super.onOptionsItemSelected(inputItem);
|
||||
}
|
||||
@@ -723,7 +795,6 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
return false;
|
||||
}
|
||||
|
||||
TabLayout groupsTabLayout = findViewById(R.id.groups);
|
||||
if (groupsTabLayout.getTabCount() < 2) {
|
||||
return false;
|
||||
}
|
||||
@@ -773,6 +844,16 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
toggleSelection(inputPosition);
|
||||
}
|
||||
|
||||
private void scaleScreen() {
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
int screenHeight = displayMetrics.heightPixels;
|
||||
float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics());
|
||||
boolean shouldScaleSmaller = screenHeight < mediumSizePx;
|
||||
|
||||
binding.include.welcomeIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private void toggleSelection(int inputPosition) {
|
||||
mAdapter.toggleSelection(inputPosition);
|
||||
int count = mAdapter.getSelectedItemCount();
|
||||
@@ -791,11 +872,10 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
boolean hasStarred = false;
|
||||
boolean hasUnstarred = false;
|
||||
|
||||
if(!mArchiveMode) {
|
||||
if (!mArchiveMode) {
|
||||
unarchiveItem.setVisible(false);
|
||||
archiveItem.setVisible(true);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
unarchiveItem.setVisible(true);
|
||||
archiveItem.setVisible(false);
|
||||
}
|
||||
@@ -854,15 +934,22 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard
|
||||
return;
|
||||
}
|
||||
|
||||
Intent i = new Intent(this, LoyaltyCardViewActivity.class);
|
||||
i.setAction("");
|
||||
Intent intent = new Intent(this, LoyaltyCardViewActivity.class);
|
||||
intent.setAction("");
|
||||
final Bundle b = new Bundle();
|
||||
b.putInt("id", loyaltyCard.id);
|
||||
i.putExtras(b);
|
||||
|
||||
ArrayList<Integer> cardList = new ArrayList<>();
|
||||
for (int i = 0; i < mAdapter.getItemCount(); i++) {
|
||||
cardList.add(mAdapter.getCard(i).id);
|
||||
}
|
||||
|
||||
b.putIntegerArrayList("cardList", cardList);
|
||||
intent.putExtras(b);
|
||||
|
||||
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard);
|
||||
|
||||
startActivity(i);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -25,8 +26,11 @@ import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.databinding.ActivityManageGroupBinding;
|
||||
|
||||
public class ManageGroupActivity extends CatimaAppCompatActivity implements ManageGroupCursorAdapter.CardAdapterListener {
|
||||
|
||||
private ActivityManageGroupBinding binding;
|
||||
private SQLiteDatabase mDatabase;
|
||||
private ManageGroupCursorAdapter mAdapter;
|
||||
|
||||
@@ -35,7 +39,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
|
||||
protected Group mGroup = null;
|
||||
private RecyclerView mCardList;
|
||||
private TextView mHelpText;
|
||||
private TextView noGroupCardsText;
|
||||
private EditText mGroupNameText;
|
||||
|
||||
private boolean mGroupNameNotInUse;
|
||||
@@ -43,17 +47,18 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
@Override
|
||||
protected void onCreate(Bundle inputSavedInstanceState) {
|
||||
super.onCreate(inputSavedInstanceState);
|
||||
setContentView(R.layout.activity_manage_group);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
binding = ActivityManageGroupBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
mDatabase = new DBHelper(this).getWritableDatabase();
|
||||
|
||||
mHelpText = findViewById(R.id.helpText);
|
||||
mCardList = findViewById(R.id.list);
|
||||
FloatingActionButton saveButton = findViewById(R.id.fabSave);
|
||||
noGroupCardsText = binding.include.noGroupCardsText;
|
||||
mCardList = binding.include.list;
|
||||
FloatingActionButton saveButton = binding.fabSave;
|
||||
|
||||
mGroupNameText = findViewById(R.id.editTextGroupName);
|
||||
mGroupNameText = binding.editTextGroupName;
|
||||
|
||||
mGroupNameText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
@@ -105,12 +110,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
mGroupNameText.setText(inputSavedInstanceState.getString(SAVE_INSTANCE_CURRENT_GROUP_NAME));
|
||||
}
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar == null) {
|
||||
throw (new RuntimeException("mActionBar is not expected to be null here"));
|
||||
}
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
enableToolbarBackButton();
|
||||
|
||||
saveButton.setOnClickListener(v -> {
|
||||
String currentGroupName = mGroupNameText.getText().toString().trim();
|
||||
@@ -133,7 +133,7 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
finish();
|
||||
});
|
||||
// this setText is here because content_main.xml is reused from main activity
|
||||
mHelpText.setText(getResources().getText(R.string.noGiftCardsGroup));
|
||||
noGroupCardsText.setText(getResources().getText(R.string.noGiftCardsGroup));
|
||||
updateLoyaltyCardList();
|
||||
}
|
||||
|
||||
@@ -191,16 +191,16 @@ public class ManageGroupActivity extends CatimaAppCompatActivity implements Mana
|
||||
|
||||
if (mAdapter.getItemCount() == 0) {
|
||||
mCardList.setVisibility(View.GONE);
|
||||
mHelpText.setVisibility(View.VISIBLE);
|
||||
noGroupCardsText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mCardList.setVisibility(View.VISIBLE);
|
||||
mHelpText.setVisibility(View.GONE);
|
||||
noGroupCardsText.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void leaveWithoutSaving() {
|
||||
if (hasChanged()) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ManageGroupActivity.this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(ManageGroupActivity.this);
|
||||
builder.setTitle(R.string.leaveWithoutSaveTitle);
|
||||
builder.setMessage(R.string.leaveWithoutSaveConfirmation);
|
||||
builder.setPositiveButton(R.string.confirm, (dialog, which) -> finish());
|
||||
|
||||
@@ -8,8 +8,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class ManageGroupCursorAdapter extends LoyaltyCardCursorAdapter {
|
||||
private HashMap<Integer, Integer> mIndexCardMap;
|
||||
private HashMap<Integer, Boolean> mInGroupOverlay;
|
||||
|
||||
@@ -8,11 +8,14 @@ import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.List;
|
||||
@@ -24,7 +27,10 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import protect.card_locker.databinding.ManageGroupsActivityBinding;
|
||||
|
||||
public class ManageGroupsActivity extends CatimaAppCompatActivity implements GroupCursorAdapter.GroupAdapterListener {
|
||||
private ManageGroupsActivityBinding binding;
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private SQLiteDatabase mDatabase;
|
||||
@@ -35,14 +41,12 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ManageGroupsActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.groups);
|
||||
setContentView(R.layout.manage_groups_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
mDatabase = new DBHelper(this).getWritableDatabase();
|
||||
}
|
||||
@@ -51,12 +55,12 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
FloatingActionButton addButton = findViewById(R.id.fabAdd);
|
||||
FloatingActionButton addButton = binding.fabAdd;
|
||||
addButton.setOnClickListener(v -> createGroup());
|
||||
addButton.bringToFront();
|
||||
|
||||
mGroupList = findViewById(R.id.list);
|
||||
mHelpText = findViewById(R.id.helpText);
|
||||
mGroupList = binding.include.list;
|
||||
mHelpText = binding.include.helpText;
|
||||
|
||||
// Init group list
|
||||
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
|
||||
@@ -108,24 +112,60 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void setGroupNameError(EditText input) {
|
||||
String string = sanitizeAddGroupNameField(input.getText());
|
||||
|
||||
if (string.length() == 0) {
|
||||
input.setError(getString(R.string.group_name_is_empty));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DBHelper.getGroup(mDatabase, string) != null) {
|
||||
input.setError(getString(R.string.group_name_already_in_use));
|
||||
return;
|
||||
}
|
||||
|
||||
input.setError(null);
|
||||
}
|
||||
|
||||
private String sanitizeAddGroupNameField(CharSequence s) {
|
||||
return s.toString().trim();
|
||||
}
|
||||
|
||||
private void createGroup() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(R.string.enter_group_name);
|
||||
final EditText input = new EditText(this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
builder.setView(input);
|
||||
input.addTextChangedListener(new SimpleTextWatcher() {
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
setGroupNameError(input);
|
||||
}
|
||||
});
|
||||
setGroupNameError(input);
|
||||
|
||||
// Add spacing to EditText
|
||||
FrameLayout container = new FrameLayout(this);
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
params.leftMargin = 50;
|
||||
params.rightMargin = 50;
|
||||
input.setLayoutParams(params);
|
||||
container.addView(input);
|
||||
|
||||
builder.setView(container);
|
||||
|
||||
builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> {
|
||||
String inputString = input.getText().toString().trim();
|
||||
if (inputString.length() == 0) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_is_empty, Toast.LENGTH_SHORT).show();
|
||||
CharSequence error = input.getError();
|
||||
|
||||
if (error != null) {
|
||||
Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
if (DBHelper.getGroup(mDatabase, inputString) != null) {
|
||||
Toast.makeText(getApplicationContext(), R.string.group_name_already_in_use, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
DBHelper.insertGroup(mDatabase, inputString);
|
||||
|
||||
DBHelper.insertGroup(mDatabase, sanitizeAddGroupNameField(input.getText()));
|
||||
updateGroupList();
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel());
|
||||
@@ -193,7 +233,7 @@ public class ManageGroupsActivity extends CatimaAppCompatActivity implements Gro
|
||||
public void onDeleteButtonClicked(View view) {
|
||||
final String groupName = getGroupName(view);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this);
|
||||
builder.setTitle(R.string.deleteConfirmationGroup);
|
||||
builder.setMessage(groupName);
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class OpenWebLinkHandler {
|
||||
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
public void openBrowser(AppCompatActivity activity, String url) {
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(activity, R.string.failedToOpenUrl, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
app/src/main/java/protect/card_locker/PermissionUtils.java
Normal file
94
app/src/main/java/protect/card_locker/PermissionUtils.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class PermissionUtils {
|
||||
/**
|
||||
* Check if storage read permission is needed.
|
||||
*
|
||||
* This is only necessary on Android 6.0 (Marshmallow) and below. See
|
||||
* https://github.com/CatimaLoyalty/Android/issues/979 for more info.
|
||||
*
|
||||
* @param activity
|
||||
* @return
|
||||
*/
|
||||
private static boolean needsStorageReadPermission(Activity activity) {
|
||||
// Testing showed this permission wasn't needed for anything Catima did past Marshmallow
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if camera permission is needed.
|
||||
*
|
||||
* @param activity
|
||||
* @return
|
||||
*/
|
||||
public static boolean needsCameraPermission(Activity activity) {
|
||||
// Android only introduced the runtime permission system in Marshmallow (Android 6.0)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call onRequestPermissionsResult after storage read permission was granted.
|
||||
* Mocks a successful grant if a grant is not necessary.
|
||||
*
|
||||
* @param activity
|
||||
* @param requestCode
|
||||
*/
|
||||
public static void requestStorageReadPermission(CatimaAppCompatActivity activity, int requestCode) {
|
||||
String[] permissions = new String[]{ android.Manifest.permission.READ_EXTERNAL_STORAGE };
|
||||
int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED };
|
||||
|
||||
if (needsStorageReadPermission(activity)) {
|
||||
ActivityCompat.requestPermissions(activity, permissions, requestCode);
|
||||
} else {
|
||||
// FIXME: This points to onMockedRequestPermissionResult instead of to
|
||||
// onRequestPermissionResult because onRequestPermissionResult was only introduced in
|
||||
// Android 6.0 (SDK 23) and we and to support Android 5.0 (SDK 21) too.
|
||||
//
|
||||
// When minSdk becomes 23, this should point to onRequestPermissionResult directly and
|
||||
// the activity input variable should be changed from CatimaAppCompatActivity to
|
||||
// Activity.
|
||||
activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call onRequestPermissionsResult after camera permission was granted.
|
||||
* Mocks a successful grant if a grant is not necessary.
|
||||
*
|
||||
* @param activity
|
||||
* @param requestCode
|
||||
*/
|
||||
public static void requestCameraPermission(CatimaAppCompatActivity activity, int requestCode) {
|
||||
String[] permissions = new String[]{ Manifest.permission.CAMERA };
|
||||
int[] mockedResults = new int[]{ PackageManager.PERMISSION_GRANTED };
|
||||
|
||||
if (needsCameraPermission(activity)) {
|
||||
ActivityCompat.requestPermissions(activity, permissions, requestCode);
|
||||
} else {
|
||||
// FIXME: This points to onMockedRequestPermissionResult instead of to
|
||||
// onRequestPermissionResult because onRequestPermissionResult was only introduced in
|
||||
// Android 6.0 (SDK 23) and we and to support Android 5.0 (SDK 21) too.
|
||||
//
|
||||
// When minSdk becomes 23, this should point to onRequestPermissionResult directly and
|
||||
// the activity input variable should be changed from CatimaAppCompatActivity to
|
||||
// Activity.
|
||||
activity.onMockedRequestPermissionsResult(requestCode, permissions, mockedResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,31 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import com.journeyapps.barcodescanner.BarcodeCallback;
|
||||
@@ -20,10 +35,8 @@ import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import protect.card_locker.databinding.CustomBarcodeScannerBinding;
|
||||
import protect.card_locker.databinding.ScanActivityBinding;
|
||||
|
||||
/**
|
||||
* Custom Scannner Activity extending from Activity to display a custom layout form scanner view.
|
||||
@@ -32,8 +45,16 @@ import androidx.appcompat.widget.Toolbar;
|
||||
* originally licensed under Apache 2.0
|
||||
*/
|
||||
public class ScanActivity extends CatimaAppCompatActivity {
|
||||
|
||||
private ScanActivityBinding binding;
|
||||
private CustomBarcodeScannerBinding customBarcodeScannerBinding;
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
private static final int MEDIUM_SCALE_FACTOR_DIP = 460;
|
||||
private static final int COMPAT_SCALE_FACTOR_DIP = 320;
|
||||
|
||||
private static final int PERMISSION_SCAN_ADD_FROM_IMAGE = 100;
|
||||
|
||||
private CaptureManager capture;
|
||||
private DecoratedBarcodeView barcodeScannerView;
|
||||
|
||||
@@ -55,23 +76,22 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ScanActivityBinding.inflate(getLayoutInflater());
|
||||
customBarcodeScannerBinding = CustomBarcodeScannerBinding.bind(binding.zxingBarcodeScanner);
|
||||
setTitle(R.string.scanCardBarcode);
|
||||
setContentView(R.layout.scan_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
extractIntentFields(getIntent());
|
||||
|
||||
manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData()));
|
||||
photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData()));
|
||||
findViewById(R.id.add_from_image).setOnClickListener(this::addFromImage);
|
||||
findViewById(R.id.add_manually).setOnClickListener(this::addManually);
|
||||
customBarcodeScannerBinding.addFromImage.setOnClickListener(this::addFromImage);
|
||||
customBarcodeScannerBinding.addManually.setOnClickListener(this::addManually);
|
||||
|
||||
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
|
||||
barcodeScannerView = binding.zxingBarcodeScanner;
|
||||
|
||||
// Even though we do the actual decoding with the barcodeScannerView
|
||||
// CaptureManager needs to be running to show the camera and scanning bar
|
||||
@@ -108,6 +128,10 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
capture.onResume();
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
|
||||
showCameraPermissionMissingText(false);
|
||||
}
|
||||
scaleScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,8 +228,74 @@ public class ScanActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
public void addFromImage(View view) {
|
||||
PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_IMAGE);
|
||||
}
|
||||
|
||||
private void addFromImageAfterPermission() {
|
||||
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
|
||||
photoPickerIntent.setType("image/*");
|
||||
photoPickerLauncher.launch(photoPickerIntent);
|
||||
Intent contentIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
contentIntent.setType("image/*");
|
||||
|
||||
Intent chooserIntent = Intent.createChooser(photoPickerIntent, getString(R.string.addFromImage));
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { contentIntent });
|
||||
try {
|
||||
photoPickerLauncher.launch(chooserIntent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.failedLaunchingPhotoPicker, Toast.LENGTH_LONG).show();
|
||||
Log.e(TAG, "No activity found to handle intent", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void showCameraPermissionMissingText(boolean show) {
|
||||
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedClickableArea.setOnClickListener(show ? v -> {
|
||||
navigateToSystemPermissionSetting();
|
||||
} : null);
|
||||
customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(show ? obtainThemeAttribute(R.attr.colorSurface) : Color.TRANSPARENT);
|
||||
customBarcodeScannerBinding.cameraPermissionDeniedLayout.getRoot().setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void scaleScreen() {
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
int screenHeight = displayMetrics.heightPixels;
|
||||
float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics());
|
||||
boolean shouldScaleSmaller = screenHeight < mediumSizePx;
|
||||
|
||||
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
|
||||
customBarcodeScannerBinding.cameraPermissionDeniedLayout.cameraPermissionDeniedTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private int obtainThemeAttribute(int attribute) {
|
||||
TypedValue typedValue = new TypedValue();
|
||||
getTheme().resolveAttribute(attribute, typedValue, true);
|
||||
return typedValue.data;
|
||||
}
|
||||
|
||||
private void navigateToSystemPermissionSetting() {
|
||||
Intent permissionIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", getPackageName(), null));
|
||||
permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(permissionIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
onMockedRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
if (requestCode == CaptureManager.getCameraPermissionReqCode()) {
|
||||
showCameraPermissionMissingText(!granted);
|
||||
} else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) {
|
||||
if (granted) {
|
||||
addFromImageAfterPermission();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.storageReadPermissionRequired, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,8 @@ public class ThirdPartyInfo {
|
||||
public String license() {
|
||||
return mLicense;
|
||||
}
|
||||
|
||||
public String toHtml() {
|
||||
return String.format("<a href=\"%s\">%s</a> (%s)", url(), name(), license());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,15 @@ import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import com.yalantis.ucrop.UCropActivity;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import com.yalantis.ucrop.UCropActivity;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
public class UCropWrapper extends UCropActivity {
|
||||
public static final String UCROP_TOOLBAR_TYPEFACE_STYLE = "ucop_toolbar_typeface_style";
|
||||
@@ -28,7 +29,9 @@ public class UCropWrapper extends UCropActivity {
|
||||
boolean darkMode = Utils.isDarkModeEnabled(this);
|
||||
// setup status bar to look like the rest of the app
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(darkMode ? 0 : View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
View decorView = getWindow().getDecorView();
|
||||
WindowInsetsControllerCompat wic = new WindowInsetsControllerCompat(getWindow(), decorView);
|
||||
wic.setAppearanceLightStatusBars(!darkMode);
|
||||
} else {
|
||||
// icons are always white back then
|
||||
if (!darkMode) {
|
||||
|
||||
@@ -11,15 +11,23 @@ import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ImageDecoder;
|
||||
import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.LocaleList;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.RawRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.palette.graphics.Palette;
|
||||
|
||||
import com.google.android.material.color.DynamicColors;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
@@ -29,14 +37,20 @@ import com.google.zxing.RGBLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
@@ -44,12 +58,6 @@ import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
|
||||
import androidx.palette.graphics.Palette;
|
||||
import protect.card_locker.preferences.Settings;
|
||||
|
||||
public class Utils {
|
||||
@@ -119,12 +127,8 @@ public class Utils {
|
||||
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), intent.getData());
|
||||
bitmap = ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
|
||||
} else {
|
||||
bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), intent.getData());
|
||||
}
|
||||
Uri data = intent.getData();
|
||||
bitmap = retrieveImageFromUri(context, data);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error getting data from image file");
|
||||
e.printStackTrace();
|
||||
@@ -164,6 +168,20 @@ public class Utils {
|
||||
throw new UnsupportedOperationException("Unknown request code for parseSetBarcodeActivityResult");
|
||||
}
|
||||
|
||||
static public Bitmap retrieveImageFromUri(Context context, Uri data) throws IOException {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ImageDecoder.Source image_source = ImageDecoder.createSource(context.getContentResolver(), data);
|
||||
return ImageDecoder.decodeBitmap(image_source, (decoder, info, source) -> decoder.setMutableRequired(true));
|
||||
} else {
|
||||
return getBitmapSdkLessThan29(data, context);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static Bitmap getBitmapSdkLessThan29(Uri data, Context context) throws IOException {
|
||||
return MediaStore.Images.Media.getBitmap(context.getContentResolver(), data);
|
||||
}
|
||||
|
||||
static public BarcodeValues getBarcodeFromBitmap(Bitmap bitmap) {
|
||||
// This function is vulnerable to OOM, so we try again with a smaller bitmap is we get OOM
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -197,7 +215,21 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
static public Boolean isNotYetValid(Date validFromDate) {
|
||||
// The note in `hasExpired` does not apply here, since the bug was fixed before this feature was added.
|
||||
return validFromDate.after(getStartOfToday().getTime());
|
||||
}
|
||||
|
||||
static public Boolean hasExpired(Date expiryDate) {
|
||||
// Note: In #1083 it was discovered that `DatePickerFragment` may sometimes store the expiryDate
|
||||
// at 12:00 PM instead of 12:00 AM in the DB. While this has been fixed and the 12-hour difference
|
||||
// is not a problem for the way the comparison currently works, it's good to keep in mind such
|
||||
// dates may exist in the DB in case the comparison changes in the future and the new one relies
|
||||
// on both dates being set at 12:00 AM.
|
||||
return expiryDate.before(getStartOfToday().getTime());
|
||||
}
|
||||
|
||||
static private Calendar getStartOfToday() {
|
||||
// today
|
||||
Calendar date = new GregorianCalendar();
|
||||
// reset hour, minutes, seconds and millis
|
||||
@@ -205,8 +237,7 @@ public class Utils {
|
||||
date.set(Calendar.MINUTE, 0);
|
||||
date.set(Calendar.SECOND, 0);
|
||||
date.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return expiryDate.before(date.getTime());
|
||||
return date;
|
||||
}
|
||||
|
||||
static public String formatBalance(Context context, BigDecimal value, Currency currency) {
|
||||
@@ -239,32 +270,19 @@ public class Utils {
|
||||
return numberFormat.format(value);
|
||||
}
|
||||
|
||||
static public Boolean currencyHasDecimals(Currency currency) {
|
||||
static public BigDecimal parseBalance(String value, Currency currency) throws ParseException {
|
||||
NumberFormat numberFormat = NumberFormat.getInstance();
|
||||
|
||||
if (currency == null) {
|
||||
return false;
|
||||
numberFormat.setMaximumFractionDigits(0);
|
||||
} else {
|
||||
numberFormat.setMinimumFractionDigits(currency.getDefaultFractionDigits());
|
||||
numberFormat.setMaximumFractionDigits(currency.getDefaultFractionDigits());
|
||||
}
|
||||
|
||||
return currency.getDefaultFractionDigits() != 0;
|
||||
}
|
||||
Log.d(TAG, numberFormat.parse(value).toString());
|
||||
|
||||
static public BigDecimal parseCurrency(String value, Boolean hasDecimals) throws NumberFormatException {
|
||||
// If there are no decimals expected, remove all separators before parsing
|
||||
if (!hasDecimals) {
|
||||
value = value.replaceAll("[^0-9]", "");
|
||||
return new BigDecimal(value);
|
||||
}
|
||||
|
||||
// There are many ways users can write a currency, so we fix it up a bit
|
||||
// 1. Replace all non-numbers with dots
|
||||
value = value.replaceAll("[^0-9]", ".");
|
||||
|
||||
// 2. Remove all but the last dot
|
||||
while (value.split("\\.").length > 2) {
|
||||
value = value.replaceFirst("\\.", "");
|
||||
}
|
||||
|
||||
// Parse as BigDecimal
|
||||
return new BigDecimal(value);
|
||||
return new BigDecimal(numberFormat.parse(value).toString());
|
||||
}
|
||||
|
||||
static public byte[] bitmapToByteArray(Bitmap bitmap) {
|
||||
@@ -359,6 +377,14 @@ public class Utils {
|
||||
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, type));
|
||||
}
|
||||
|
||||
public static File retrieveCardImageAsFile(Context context, String fileName) {
|
||||
return context.getFileStreamPath(fileName);
|
||||
}
|
||||
|
||||
public static File retrieveCardImageAsFile(Context context, int loyaltyCardId, ImageLocationType type) {
|
||||
return retrieveCardImageAsFile(context, getCardImageFileName(loyaltyCardId, type));
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, String fileName) {
|
||||
FileInputStream in;
|
||||
try {
|
||||
@@ -402,8 +428,7 @@ public class Utils {
|
||||
Resources res = context.getResources();
|
||||
Configuration configuration = res.getConfiguration();
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
|
||||
res.updateConfiguration(configuration, res.getDisplayMetrics());
|
||||
setLocalesSdkLessThan24(chosenLocale, configuration, res);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -413,6 +438,12 @@ public class Utils {
|
||||
return context.createConfigurationContext(configuration);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static void setLocalesSdkLessThan24(Locale chosenLocale, Configuration configuration, Resources res) {
|
||||
configuration.locale = chosenLocale != null ? chosenLocale : Locale.getDefault();
|
||||
res.updateConfiguration(configuration, res.getDisplayMetrics());
|
||||
}
|
||||
|
||||
static public long getUnixTime() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
@@ -494,7 +525,7 @@ public class Utils {
|
||||
} else {
|
||||
// final catch all in case of invalid theme value from older versions
|
||||
// also handles R.string.settings_key_system_theme
|
||||
DynamicColors.applyIfAvailable(activity);
|
||||
DynamicColors.applyToActivityIfAvailable(activity);
|
||||
}
|
||||
|
||||
if (isDarkModeEnabled(activity) && settings.getOledDark()) {
|
||||
@@ -534,4 +565,23 @@ public class Utils {
|
||||
final int color = (int) (Math.random() * colors.length());
|
||||
return colors.getColor(color, Color.BLACK);
|
||||
}
|
||||
|
||||
public static String readTextFile(Context context, @RawRes int resourceId) throws IOException {
|
||||
InputStream input = context.getResources().openRawResource(resourceId);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
StringBuilder result = new StringBuilder();
|
||||
while (true) {
|
||||
String nextLine = reader.readLine();
|
||||
|
||||
if (nextLine == null || nextLine.isEmpty()) {
|
||||
reader.close();
|
||||
break;
|
||||
}
|
||||
|
||||
result.append("\n");
|
||||
result.append(nextLine);
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,15 @@ import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ZipUtils {
|
||||
static public String read(ZipInputStream zipInputStream) throws IOException {
|
||||
public static Bitmap readImage(ZipInputStream zipInputStream) {
|
||||
return BitmapFactory.decodeStream(zipInputStream);
|
||||
}
|
||||
|
||||
public static JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
|
||||
return new JSONObject(read(zipInputStream));
|
||||
}
|
||||
|
||||
private static String read(ZipInputStream zipInputStream) throws IOException {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Reader reader = new BufferedReader(new InputStreamReader(zipInputStream, StandardCharsets.UTF_8));
|
||||
int c;
|
||||
@@ -24,12 +32,4 @@ public class ZipUtils {
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
static public Bitmap readImage(ZipInputStream zipInputStream) {
|
||||
return BitmapFactory.decodeStream(zipInputStream);
|
||||
}
|
||||
|
||||
static public JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
|
||||
return new JSONObject(read(zipInputStream));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ public class CatimaExporter implements Exporter {
|
||||
printer.printRecord(DBHelper.LoyaltyCardDbIds.ID,
|
||||
DBHelper.LoyaltyCardDbIds.STORE,
|
||||
DBHelper.LoyaltyCardDbIds.NOTE,
|
||||
DBHelper.LoyaltyCardDbIds.VALID_FROM,
|
||||
DBHelper.LoyaltyCardDbIds.EXPIRY,
|
||||
DBHelper.LoyaltyCardDbIds.BALANCE,
|
||||
DBHelper.LoyaltyCardDbIds.BALANCE_TYPE,
|
||||
@@ -146,6 +147,7 @@ public class CatimaExporter implements Exporter {
|
||||
printer.printRecord(card.id,
|
||||
card.store,
|
||||
card.note,
|
||||
card.validFrom != null ? card.validFrom.getTime() : "",
|
||||
card.expiry != null ? card.expiry.getTime() : "",
|
||||
card.balance,
|
||||
card.balanceType,
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -55,7 +54,7 @@ public class CatimaImporter implements Importer {
|
||||
|
||||
String fileName = Uri.parse(localFileHeader.getFileName()).getLastPathSegment();
|
||||
if (fileName.equals("catima.csv")) {
|
||||
importCSV(context, database, new ByteArrayInputStream(ZipUtils.read(zipInputStream).getBytes(StandardCharsets.UTF_8)));
|
||||
importCSV(context, database, zipInputStream);
|
||||
} else if (fileName.endsWith(".png")) {
|
||||
Utils.saveCardImage(context, ZipUtils.readImage(zipInputStream), fileName);
|
||||
} else {
|
||||
@@ -68,23 +67,14 @@ public class CatimaImporter implements Importer {
|
||||
bufferedInputStream.reset();
|
||||
importCSV(context, database, bufferedInputStream);
|
||||
}
|
||||
|
||||
input.close();
|
||||
}
|
||||
|
||||
public void importCSV(Context context, SQLiteDatabase database, InputStream input) throws IOException, FormatException, InterruptedException {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
|
||||
bufferedReader.mark(100);
|
||||
|
||||
Integer version = 1;
|
||||
|
||||
try {
|
||||
version = Integer.parseInt(bufferedReader.readLine());
|
||||
} catch (NumberFormatException _e) {
|
||||
// Assume version 1
|
||||
}
|
||||
|
||||
bufferedReader.reset();
|
||||
|
||||
int version = parseVersion(bufferedReader);
|
||||
switch (version) {
|
||||
case 1:
|
||||
parseV1(context, database, bufferedReader);
|
||||
@@ -95,8 +85,6 @@ public class CatimaImporter implements Importer {
|
||||
default:
|
||||
throw new FormatException(String.format("No code to parse version %s", version));
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
}
|
||||
|
||||
public void parseV1(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
|
||||
@@ -118,8 +106,8 @@ public class CatimaImporter implements Importer {
|
||||
}
|
||||
|
||||
public void parseV2(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException {
|
||||
Integer part = 0;
|
||||
String stringPart = "";
|
||||
int part = 0;
|
||||
StringBuilder stringPart = new StringBuilder();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
@@ -135,7 +123,7 @@ public class CatimaImporter implements Importer {
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
parseV2Groups(database, stringPart);
|
||||
parseV2Groups(database, stringPart.toString());
|
||||
sectionParsed = true;
|
||||
} catch (FormatException e) {
|
||||
// We may have a multiline field, try again
|
||||
@@ -143,7 +131,7 @@ public class CatimaImporter implements Importer {
|
||||
break;
|
||||
case 2:
|
||||
try {
|
||||
parseV2Cards(context, database, stringPart);
|
||||
parseV2Cards(context, database, stringPart.toString());
|
||||
sectionParsed = true;
|
||||
} catch (FormatException e) {
|
||||
// We may have a multiline field, try again
|
||||
@@ -151,7 +139,7 @@ public class CatimaImporter implements Importer {
|
||||
break;
|
||||
case 3:
|
||||
try {
|
||||
parseV2CardGroups(database, stringPart);
|
||||
parseV2CardGroups(database, stringPart.toString());
|
||||
sectionParsed = true;
|
||||
} catch (FormatException e) {
|
||||
// We may have a multiline field, try again
|
||||
@@ -167,12 +155,12 @@ public class CatimaImporter implements Importer {
|
||||
|
||||
if (sectionParsed) {
|
||||
part += 1;
|
||||
stringPart = "";
|
||||
stringPart = new StringBuilder();
|
||||
} else {
|
||||
stringPart += tmp + "\n";
|
||||
stringPart.append(tmp).append('\n');
|
||||
}
|
||||
} else {
|
||||
stringPart += tmp + "\n";
|
||||
stringPart.append(tmp).append('\n');
|
||||
}
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
@@ -255,6 +243,35 @@ public class CatimaImporter implements Importer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the version number of the import file
|
||||
*
|
||||
* @param reader the reader containing the import file
|
||||
* @return the parsed version number, defaulting to 1 if none is found
|
||||
* @throws IOException there was a problem reading the file
|
||||
*/
|
||||
private int parseVersion(BufferedReader reader) throws IOException {
|
||||
reader.mark(10); // slightly over the search limit just to be sure
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int searchLimit = 5; // gives you version numbers up to 99999
|
||||
int codePoint;
|
||||
// search until the next whitespace, indicating the end of the version
|
||||
while (!Character.isWhitespace(codePoint = reader.read())) {
|
||||
// we found something that isn't a digit, or we ran out of chars
|
||||
if (!Character.isDigit(codePoint) || searchLimit <= 0) {
|
||||
reader.reset();
|
||||
return 1; // default value
|
||||
}
|
||||
sb.append((char) codePoint);
|
||||
searchLimit--;
|
||||
}
|
||||
reader.reset();
|
||||
if (sb.length() == 0) {
|
||||
return 1;
|
||||
}
|
||||
return Integer.parseInt(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a single loyalty card into the database using the given
|
||||
* session.
|
||||
@@ -269,6 +286,12 @@ public class CatimaImporter implements Importer {
|
||||
}
|
||||
|
||||
String note = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.NOTE, record, "");
|
||||
Date validFrom = null;
|
||||
try {
|
||||
validFrom = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.VALID_FROM, record, true));
|
||||
} catch (NullPointerException | FormatException e) {
|
||||
}
|
||||
|
||||
Date expiry = null;
|
||||
try {
|
||||
expiry = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record, true));
|
||||
@@ -338,7 +361,7 @@ public class CatimaImporter implements Importer {
|
||||
// We catch this exception so we can still import old backups
|
||||
}
|
||||
|
||||
DBHelper.insertLoyaltyCard(database, id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus, lastUsed,archiveStatus);
|
||||
DBHelper.insertLoyaltyCard(database, id, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus, lastUsed, archiveStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,4 +386,4 @@ public class CatimaImporter implements Importer {
|
||||
cardGroups.add(DBHelper.getGroup(database, groupId));
|
||||
DBHelper.setLoyaltyCardGroups(database, cardId, cardGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,10 @@ public class FidmeImporter implements Importer {
|
||||
// The ID is called reference
|
||||
String cardId = CSVHelpers.extractString("Reference", record, "");
|
||||
if (cardId.isEmpty()) {
|
||||
throw new FormatException("No card ID listed, but is required");
|
||||
// Fidme deletes the card id if a card is expired
|
||||
// Because Catima considers the card id a required field, we ignore these expired cards
|
||||
// https://github.com/CatimaLoyalty/Android/issues/1005
|
||||
return;
|
||||
}
|
||||
|
||||
// Sadly, Fidme exports don't contain the card type
|
||||
@@ -125,6 +128,6 @@ public class FidmeImporter implements Importer {
|
||||
|
||||
// TODO: Front and back image
|
||||
|
||||
DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, starStatus, null,archiveStatus);
|
||||
DBHelper.insertLoyaltyCard(database, store, note, null, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, starStatus, null,archiveStatus);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class MultiFormatExporter {
|
||||
|
||||
@@ -6,13 +6,7 @@ import android.util.Log;
|
||||
|
||||
import net.lingala.zip4j.exception.ZipException;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.ParseException;
|
||||
|
||||
import protect.card_locker.FormatException;
|
||||
|
||||
public class MultiFormatImporter {
|
||||
private static final String TAG = "Catima";
|
||||
|
||||
@@ -234,7 +234,7 @@ public class StocardImporter implements Importer {
|
||||
headerColor = Utils.getHeaderColorFromImage(cardIcon, headerColor);
|
||||
}
|
||||
|
||||
long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, 0, null,0);
|
||||
long loyaltyCardInternalId = DBHelper.insertLoyaltyCard(database, store, note, null, null, BigDecimal.valueOf(0), null, cardId, null, barcodeType, headerColor, 0, null,0);
|
||||
|
||||
if (cardIcon != null) {
|
||||
Utils.saveCardImage(context, cardIcon, (int) loyaltyCardInternalId, ImageLocationType.icon);
|
||||
|
||||
@@ -126,7 +126,7 @@ public class VoucherVaultImporter implements Importer {
|
||||
throw new FormatException("Unknown colour type found: " + colorFromJSON);
|
||||
}
|
||||
|
||||
DBHelper.insertLoyaltyCard(database, store, "", expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0, Utils.getUnixTime(),0);
|
||||
DBHelper.insertLoyaltyCard(database, store, "", null, expiry, balance, balanceType, cardId, null, barcodeType, headerColor, 0, Utils.getUnixTime(),0);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
|
||||
@@ -9,7 +9,6 @@ import androidx.annotation.IntegerRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.google.android.material.color.DynamicColors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -15,35 +17,35 @@ import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentResultListener;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import com.google.android.material.color.DynamicColors;
|
||||
|
||||
import kotlin.Suppress;
|
||||
import nl.invissvenska.numberpickerpreference.NumberDialogPreference;
|
||||
import nl.invissvenska.numberpickerpreference.NumberPickerPreferenceDialogFragment;
|
||||
import protect.card_locker.CatimaAppCompatActivity;
|
||||
import protect.card_locker.MainActivity;
|
||||
import protect.card_locker.R;
|
||||
import protect.card_locker.Utils;
|
||||
import protect.card_locker.databinding.SettingsActivityBinding;
|
||||
|
||||
public class SettingsActivity extends CatimaAppCompatActivity {
|
||||
|
||||
private SettingsActivityBinding binding;
|
||||
private final static String RELOAD_MAIN_STATE = "mReloadMain";
|
||||
private SettingsFragment fragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = SettingsActivityBinding.inflate(getLayoutInflater());
|
||||
setTitle(R.string.settings);
|
||||
setContentView(R.layout.settings_activity);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setContentView(binding.getRoot());
|
||||
Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
enableToolbarBackButton();
|
||||
|
||||
// Display the fragment as the main content.
|
||||
fragment = new SettingsFragment();
|
||||
@@ -164,6 +166,11 @@ public class SettingsActivity extends CatimaAppCompatActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // setTargetFragment
|
||||
// androidx.preference.PreferenceDialogFragmentCompat uses the deprecated method
|
||||
// `getTargetFragment()`, which throws if `setTargetFragment()` isn't used before.
|
||||
// While this isn't fixed on upstream, suppress the deprecation warning
|
||||
// https://issuetracker.google.com/issues/181793702
|
||||
public void onDisplayPreferenceDialog(Preference preference) {
|
||||
if (preference instanceof NumberDialogPreference) {
|
||||
NumberDialogPreference dialogPreference = (NumberDialogPreference) preference;
|
||||
|
||||
10
app/src/main/res/anim/slide_in_left.xml
Normal file
10
app/src/main/res/anim/slide_in_left.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- https://stackoverflow.com/questions/5151591/android-left-to-right-slide-animation/5151774#5151774 -->
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromXDelta="-100%"
|
||||
android:fromYDelta="0%"
|
||||
android:toXDelta="0%"
|
||||
android:toYDelta="0%" />
|
||||
</set>
|
||||
10
app/src/main/res/anim/slide_in_right.xml
Normal file
10
app/src/main/res/anim/slide_in_right.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- https://stackoverflow.com/questions/5151591/android-left-to-right-slide-animation/5151774#5151774 -->
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromXDelta="100%"
|
||||
android:fromYDelta="0%"
|
||||
android:toXDelta="0%"
|
||||
android:toYDelta="0%" />
|
||||
</set>
|
||||
10
app/src/main/res/anim/slide_out_left.xml
Normal file
10
app/src/main/res/anim/slide_out_left.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- https://stackoverflow.com/questions/5151591/android-left-to-right-slide-animation/5151774#5151774 -->
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromXDelta="0%"
|
||||
android:fromYDelta="0%"
|
||||
android:toXDelta="-100%"
|
||||
android:toYDelta="0%" />
|
||||
</set>
|
||||
10
app/src/main/res/anim/slide_out_right.xml
Normal file
10
app/src/main/res/anim/slide_out_right.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- https://stackoverflow.com/questions/5151591/android-left-to-right-slide-animation/5151774#5151774 -->
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromXDelta="0%"
|
||||
android:fromYDelta="0%"
|
||||
android:toXDelta="100%"
|
||||
android:toYDelta="0%" />
|
||||
</set>
|
||||
5
app/src/main/res/drawable/camera_permission_denied.xml
Normal file
5
app/src/main/res/drawable/camera_permission_denied.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#BD0000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M10.94,8.12L7.48,4.66L9,3h6l1.83,2H20c1.1,0 2,0.9 2,2v12c0,0.05 -0.01,0.1 -0.02,0.16l-5.1,-5.1C16.96,13.71 17,13.36 17,13c0,-2.76 -2.24,-5 -5,-5C11.64,8 11.29,8.04 10.94,8.12zM20.49,23.31L18.17,21H4c-1.1,0 -2,-0.9 -2,-2V7c0,-0.59 0.27,-1.12 0.68,-1.49l-2,-2L2.1,2.1l19.8,19.8L20.49,23.31zM14.49,17.32l-1.5,-1.5C12.67,15.92 12.35,16 12,16c-1.66,0 -3,-1.34 -3,-3c0,-0.35 0.08,-0.67 0.19,-0.98l-1.5,-1.5C7.25,11.24 7,12.09 7,13c0,2.76 2.24,5 5,5C12.91,18 13.76,17.75 14.49,17.32z"/>
|
||||
</vector>
|
||||
@@ -1,4 +1,4 @@
|
||||
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||
<vector android:autoMirrored="true" android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_baseline_info_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_info_24.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM1,2v2h2l3.6,7.59 -1.35,2.45c-0.16,0.28 -0.25,0.61 -0.25,0.96 0,1.1 0.9,2 2,2h12v-2L7.42,15c-0.14,0 -0.25,-0.11 -0.25,-0.25l0.03,-0.12 0.9,-1.63h7.45c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.08,-0.14 0.12,-0.31 0.12,-0.48 0,-0.55 -0.45,-1 -1,-1L5.21,4l-0.94,-2L1,2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||
</vector>
|
||||
@@ -2,8 +2,7 @@
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
|
||||
|
||||
27
app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
27
app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M53.26,40.92l14.35,-6.39l2.86,6.42"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M36.14,40.95l2.86,-6.42l14.24,6.34"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M40.01,37.17l7.73,3.44H38.48l1.53,-3.44m26.58,0 l1.53,3.44H58.86l7.73,-3.44M39,34.53l-2.86,6.42v1.66H70.47V40.95L67.61,34.53 53.27,40.92l-0.02,-0.05L39,34.53Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M74.07,51.23l4.93,1.41l-6.44,22.48l-37.61,-10.79l39.13,0l0,-13.11z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M34.94,40.95C31.66,40.95 29,46.19 29,52.64s2.66,11.69 5.94,11.69L74.07,64.34L74.07,40.95ZM41.21,51.08 L40.15,50.02 44.43,45.74 48.71,50.02 47.65,51.08 44.43,47.86ZM58.02,56.56a3.11,3.11 0,0 1,-2.93 2.05,3.15 3.15,0 0,1 -0.55,-0.05 3.11,3.11 0,0 1,-1.83 -1.04,3.12 3.12,0 0,1 -5.3,-0.96 0.75,0.75 0,0 1,1.41 -0.51,1.62 1.62,0 0,0 3.14,-0.55 0.75,0.75 0,0 1,1.5 0,1.62 1.62,0 0,0 3.14,0.55 0.75,0.75 0,0 1,1.41 0.51ZM64.14,51.08 L60.92,47.86L57.71,51.08l-1.06,-1.06 4.28,-4.28 4.28,4.28Z"/>
|
||||
</vector>
|
||||
16
app/src/main/res/drawable/ic_valid_from_24dp.xml
Normal file
16
app/src/main/res/drawable/ic_valid_from_24dp.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18,15.782V22l4.886,-3.109z" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11.99,2C6.47,2 2,6.48 2,12C2,17.52 6.47,22 11.99,22C13.417,22 14.772,21.699 16,21.162L16,18.928C14.823,19.608 13.458,20 12,20C7.58,20 4,16.42 4,12C4,7.58 7.58,4 12,4C16.42,4 20,7.58 20,12C20,13.061 19.791,14.073 19.416,15L21.541,15C21.839,14.053 22,13.045 22,12C22,6.48 17.52,2 11.99,2zM11,7L11,13L16,16L16,15L16.951,15L17,14.92L12.5,12.25L12.5,7L11,7z" />
|
||||
</vector>
|
||||
@@ -1,5 +0,0 @@
|
||||
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
|
||||
</vector>
|
||||
@@ -7,14 +7,15 @@
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="protect.card_locker.ManageGroupActivity">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabSave"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
app:srcCompat="@drawable/save_24dp"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/save"
|
||||
android:layout_margin="16dp" />
|
||||
app:srcCompat="@drawable/ic_done" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main"/>
|
||||
<include
|
||||
android:id="@+id/include"
|
||||
layout="@layout/content_main" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
41
app/src/main/res/layout/camera_permission_failed_layout.xml
Normal file
41
app/src/main/res/layout/camera_permission_failed_layout.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context="protect.card_locker.MainActivity"
|
||||
tools:showIn="@layout/custom_barcode_scanner">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/camera_permission_denied_clickable_area"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/camera_permission_denied_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="84dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/camera_permission_denied" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/camera_permission_denied_title"
|
||||
style="@style/TextAppearance.Material3.HeadlineLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/cameraPermissionDeniedTitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/camera_permission_denied_message"
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/noCameraPermissionDirectToSystemSetting" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
@@ -9,42 +8,63 @@
|
||||
tools:context="protect.card_locker.MainActivity"
|
||||
tools:showIn="@layout/main_activity">
|
||||
|
||||
<TextView
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:id="@+id/helpText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/noGiftCards"
|
||||
android:visibility="gone"/>
|
||||
<LinearLayout
|
||||
android:visibility="gone"
|
||||
android:id="@+id/helpSection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/welcome_icon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="184dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_launcher_foreground" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/welcome_text"
|
||||
style="@style/TextAppearance.Material3.HeadlineLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/welcome" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/add_card_instruction"
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/noGiftCards" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:id="@+id/noMatchingCardsText"
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/noMatchingGiftCards"
|
||||
android:visibility="gone"/>
|
||||
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:id="@+id/noGroupCardsText"
|
||||
style="@style/AppTheme.TextView.NoData"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/noGroupCards"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="@integer/main_view_card_columns"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="80dp"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="80dp"
|
||||
android:scrollbars="vertical"
|
||||
android:visibility="gone"/>
|
||||
|
||||
android:visibility="gone"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="@integer/main_view_card_columns" />
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -1,41 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/res/layout/custom_barcode_scanner.xml originally released under Apache 2.0 -->
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/res/layout/custom_barcode_scanner.xml originally released under Apache 2.0 -->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.journeyapps.barcodescanner.BarcodeView
|
||||
android:id="@+id/zxing_barcode_surface"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/zxing_barcode_surface"
|
||||
app:zxing_framing_rect_width="250dp"
|
||||
app:zxing_framing_rect_height="250dp"/>
|
||||
app:zxing_framing_rect_height="250dp"
|
||||
app:zxing_framing_rect_width="250dp" />
|
||||
|
||||
<com.journeyapps.barcodescanner.ViewfinderView
|
||||
android:id="@+id/zxing_viewfinder_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/zxing_viewfinder_view"
|
||||
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
|
||||
app:zxing_result_view="@color/zxing_custom_result_view"
|
||||
app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
|
||||
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask"/>
|
||||
app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/card_input_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/activity_scanner_padding">
|
||||
|
||||
<include
|
||||
android:id="@+id/camera_permission_denied_layout"
|
||||
layout="@layout/camera_permission_failed_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_from_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/addFromImage" />
|
||||
android:text="@string/addFromImage"
|
||||
app:layout_constraintBottom_toTopOf="@+id/add_manually"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/camera_permission_denied_layout"
|
||||
app:layout_constraintVertical_bias="1.0" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_manually"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/addManually" />
|
||||
</LinearLayout>
|
||||
android:text="@string/addManually"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</merge>
|
||||
@@ -12,9 +12,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
app:srcCompat="@drawable/save_24dp"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/save"
|
||||
android:layout_margin="16dp" />
|
||||
app:srcCompat="@drawable/ic_done" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -82,6 +82,17 @@
|
||||
android:contentDescription="@string/thumbnailDescription"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/thumbnailEditIcon"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Material3.FloatingActionButton"
|
||||
android:layout_width="@dimen/cardThumbnailEditOverlaySize"
|
||||
android:layout_height="@dimen/cardThumbnailEditOverlaySize"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="4dp"
|
||||
app:contentPadding="4dp"
|
||||
android:alpha="0.8"
|
||||
android:src="@drawable/ic_mode_edit_white_24dp"/>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
@@ -277,7 +288,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberDecimal"
|
||||
android:digits="0123456789.,$" />
|
||||
android:digits="0123456789,." />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@@ -300,6 +311,32 @@
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Valid from -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/inputPadding"
|
||||
android:paddingTop="@dimen/inputPadding"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!-- Valid from -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/validFromView"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:hint="@string/validFromDate"
|
||||
android:labelFor="@+id/validFromField">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/validFromField"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Expiration -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_done" />
|
||||
app:srcCompat="@drawable/ic_done"
|
||||
android:background="@color/md_theme_dark_onSelected" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/star"
|
||||
@@ -175,12 +176,31 @@
|
||||
android:drawablePadding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/info_divider"
|
||||
app:layout_constraintBottom_toTopOf="@+id/expiry"
|
||||
app:layout_constraintBottom_toTopOf="@+id/validFrom"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible"
|
||||
tools:text="525 points"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/validFrom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:drawableLeftCompat="@drawable/ic_valid_from_24dp"
|
||||
android:drawablePadding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/balance"
|
||||
app:layout_constraintBottom_toTopOf="@+id/expiry"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible"
|
||||
tools:text="Today"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiry"
|
||||
android:layout_width="match_parent"
|
||||
@@ -193,7 +213,7 @@
|
||||
app:drawableLeftCompat="@drawable/ic_baseline_access_time_24"
|
||||
android:drawablePadding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@+id/balance"
|
||||
app:layout_constraintTop_toBottomOf="@+id/validFrom"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
||||
@@ -8,238 +8,6 @@
|
||||
android:layout_height="fill_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabEdit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
app:srcCompat="@drawable/ic_mode_edit_white_24dp"
|
||||
android:contentDescription="@string/edit"
|
||||
android:layout_margin="16dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/mainLayout"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/centerGuideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5"/>
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/scalerGuideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.75"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/maximizeButton"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="0dp"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
|
||||
android:contentDescription="@string/moveBarcodeToTopOfScreen"
|
||||
app:tint="?attr/colorOnPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/mainImage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mainImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
app:layout_constraintBottom_toTopOf="@+id/centerGuideline"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/maximizeButton"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/minimizeButton"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:layout_marginTop="10dp"
|
||||
android:padding="0dp"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
|
||||
android:contentDescription="@string/moveBarcodeToCenterOfScreen"
|
||||
app:tint="?attr/colorOnPrimary"
|
||||
app:layout_constraintTop_toBottomOf="@+id/mainImage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dotIndicator"
|
||||
android:visibility="gone"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/minimizeButton"/>
|
||||
|
||||
<SeekBar
|
||||
android:contentDescription="@string/set_scale"
|
||||
android:id="@+id/barcodeScaler"
|
||||
android:visibility="gone"
|
||||
android:max="100"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/inputPadding"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
app:layout_constraintTop_toBottomOf="@+id/scalerGuideline"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardIdView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10.0dip"
|
||||
android:layout_marginRight="10.0dip"
|
||||
android:paddingBottom="80dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dotIndicator"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:textAlignment="center"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:autoSizeMinTextSize="@dimen/singleCardCardIdTextSizeMin"
|
||||
app:autoSizeMaxTextSize="@dimen/singleCardCardIdTextSizeMax"
|
||||
android:ellipsize="end"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/drop_shadow_actionbar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5.0dip"
|
||||
android:layout_gravity="top"/>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:colorBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="0px"
|
||||
android:visibility="gone"
|
||||
app:behavior_hideable="false"
|
||||
app:behavior_peekHeight="80dp"
|
||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/bottomSheetButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_gravity="top|start"
|
||||
android:contentDescription="@string/showMoreInfo"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
|
||||
app:tint="?attr/colorOnPrimary"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/bottomSheetContentWrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noteView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="all"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/groupsView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/balanceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiryView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:longClickable="true"
|
||||
android:padding="20dp"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="@dimen/singleCardNoteTextSizeMin" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
@@ -249,8 +17,7 @@
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:fitsSystemWindows="true"
|
||||
android:weightSum="1.0"
|
||||
>
|
||||
android:weightSum="1.0">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar_landscape"
|
||||
@@ -310,5 +77,214 @@
|
||||
app:srcCompat="@drawable/ic_launcher_foreground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<FrameLayout
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/mainLayout"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/centerGuideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.5"/>
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/scalerGuideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.75"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/maximizeButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:contentDescription="@string/moveBarcodeToTopOfScreen"
|
||||
android:padding="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/mainImage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_up_24"
|
||||
app:tint="?attr/colorOnPrimary"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mainImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
app:layout_constraintBottom_toTopOf="@+id/centerGuideline"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/maximizeButton"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/minimizeButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:contentDescription="@string/moveBarcodeToCenterOfScreen"
|
||||
android:padding="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/mainImage"
|
||||
app:srcCompat="@drawable/ic_baseline_arrow_drop_down_24"
|
||||
app:tint="?attr/colorOnPrimary"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dotIndicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/minimizeButton"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/barcodeScaler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/inputPadding"
|
||||
android:layout_marginStart="15.0dip"
|
||||
android:layout_marginEnd="15.0dip"
|
||||
android:contentDescription="@string/set_scale"
|
||||
android:max="100"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/scalerGuideline" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardIdView"
|
||||
android:enabled="true"
|
||||
android:textIsSelectable="true"
|
||||
android:focusable="true"
|
||||
android:longClickable="true"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="10.0dip"
|
||||
android:layout_marginRight="10.0dip"
|
||||
android:paddingBottom="80dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dotIndicator"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:textAlignment="center"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:autoSizeMinTextSize="@dimen/singleCardCardIdTextSizeMin"
|
||||
app:autoSizeMaxTextSize="@dimen/singleCardCardIdTextSizeMax"
|
||||
android:ellipsize="end"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/drop_shadow_actionbar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="5.0dip"
|
||||
android:layout_gravity="top"/>
|
||||
</FrameLayout>
|
||||
|
||||
<com.google.android.material.bottomappbar.BottomAppBar
|
||||
android:id="@+id/bottom_app_bar"
|
||||
style="@style/Widget.MaterialComponents.BottomAppBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:contentInsetLeft="0dp"
|
||||
app:contentInsetStart="0dp"
|
||||
app:contentInsetRight="0dp"
|
||||
app:contentInsetEnd="0dp"
|
||||
app:fabAlignmentMode="center">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_previous"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="left"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/ic_baseline_chevron_left_24"
|
||||
android:tooltipText="@string/previousCard"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_show_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/ic_baseline_info_24"
|
||||
android:tooltipText="@string/showMoreInfo"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="right"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/ic_baseline_chevron_right_24"
|
||||
android:tooltipText="@string/nextCard"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_update_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:background="@android:color/transparent"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:src="@drawable/ic_baseline_shopping_cart_24"
|
||||
android:tooltipText="@string/updateBalance"
|
||||
android:visibility="gone" />
|
||||
|
||||
</com.google.android.material.bottomappbar.BottomAppBar>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabEdit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_mode_edit_white_24dp"
|
||||
android:contentDescription="@string/edit"
|
||||
app:layout_anchor="@id/bottom_app_bar" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main"/>
|
||||
<include
|
||||
android:id="@+id/include"
|
||||
layout="@layout/content_main" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/group_main"/>
|
||||
<include
|
||||
android:id="@+id/include"
|
||||
layout="@layout/group_main" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||
</adaptive-icon>
|
||||
@@ -2,4 +2,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||
</adaptive-icon>
|
||||
@@ -2,102 +2,203 @@ Sylvia van Os
|
||||
Branden Archer
|
||||
J. Lavoie
|
||||
Allan Nordhøy
|
||||
Heimen Stoffels
|
||||
solokot
|
||||
Katharine Chui
|
||||
Heimen Stoffels
|
||||
Oğuz Ersen
|
||||
Katharine Chui
|
||||
mondstern
|
||||
Altonss
|
||||
IllusiveMan196
|
||||
StoyanDimitrov
|
||||
Altonss
|
||||
SlavekB
|
||||
Michael Moroni
|
||||
Gediminas Murauskas
|
||||
Petr Novák
|
||||
Joel A
|
||||
Taco
|
||||
Gediminas Murauskas
|
||||
pfaffenrodt
|
||||
laralem
|
||||
Nyatsuki
|
||||
Michael Moroni
|
||||
gallegonovato
|
||||
HudobniVolk
|
||||
Samantaz Fox
|
||||
arno-github
|
||||
Ankit Tiwari
|
||||
Sergio Paredes
|
||||
laralem
|
||||
Aayush Gupta
|
||||
huuhaa
|
||||
arshbeerSingh
|
||||
Quentin PAGÈS
|
||||
Alexander Ivanov
|
||||
arshbeerSingh
|
||||
Freddo espresso
|
||||
Silvério Santos
|
||||
Miha Frangež
|
||||
Arnis Jaundzeikars
|
||||
Kefir2105
|
||||
sr093906
|
||||
Giovanni Donisi
|
||||
mdvhimself
|
||||
Maciej Błędkowski
|
||||
Katarzyna
|
||||
echo r"0xX4H" | rev
|
||||
Magnitudee
|
||||
Olivia (Zoe)
|
||||
betsythefc
|
||||
Silvério Santos
|
||||
waffshappen
|
||||
Robin
|
||||
Eric
|
||||
ati3
|
||||
(Cliff Heraldo)
|
||||
Evgeniy Khramov
|
||||
Jane Kong
|
||||
Jiri Grönroos
|
||||
K. Herbert
|
||||
SlavekB
|
||||
Lisa A.
|
||||
Mawuena M. KODZO A.
|
||||
Max
|
||||
Still Hsu
|
||||
String E. Fighter
|
||||
Tapu
|
||||
Yurical
|
||||
Eryk Michalak
|
||||
rr-vesp
|
||||
alajemba-vik
|
||||
/usr/local/ΕΨΗΕΛΩΝ
|
||||
Adolfo Jayme-Barrientos
|
||||
Alessandro Mandelli
|
||||
KovalevArtem
|
||||
Artem M.
|
||||
Astrohops1
|
||||
BMN
|
||||
BootVirtual
|
||||
Clonewayx
|
||||
D. Domig
|
||||
Diego
|
||||
Freddo espresso
|
||||
Fede Pujol
|
||||
francescbassas
|
||||
Jean-Luc Tibaux
|
||||
Jesse Davids
|
||||
Lukas Grassauer
|
||||
bittin
|
||||
Marnick L'Eau
|
||||
Michalis
|
||||
Michał
|
||||
Mohamed A. Salah
|
||||
the7thNightmare
|
||||
Rishi Agarwal
|
||||
Rosdyana Kusuma
|
||||
umoenks
|
||||
Simon Rusinov
|
||||
Siriusmart
|
||||
Mritunjay
|
||||
Tarik Dzambic
|
||||
Thomas Bertels
|
||||
Thomas Cruveilher
|
||||
Tian Jiale
|
||||
Tong Liu
|
||||
Wanath
|
||||
Runner
|
||||
ce i moa
|
||||
inesre
|
||||
lgasp
|
||||
phlostically
|
||||
sal0max
|
||||
Ágata Leuck
|
||||
BmBKun
|
||||
Aditya Das
|
||||
Asier
|
||||
Kevin Sicong Jiang
|
||||
Tomer Ben-Rachel
|
||||
tfuxu
|
||||
Ahmed Saleh
|
||||
Airat
|
||||
Alexander
|
||||
sNiXx
|
||||
BMN
|
||||
Angela Enogieru
|
||||
AnimeshChatterjee1
|
||||
Ashish Yadav
|
||||
Asier
|
||||
Aya Elsaadany
|
||||
Biren
|
||||
Booc Sylvan
|
||||
Brage Nesteby Reitan
|
||||
CherryMonster222
|
||||
Colgrave
|
||||
Csaba
|
||||
Mylou53
|
||||
danieluhrinyi
|
||||
Kasina Dheeraj
|
||||
Eric
|
||||
Donno
|
||||
Flav
|
||||
Franciszek Stefan
|
||||
Giovanni
|
||||
Grzegorz
|
||||
gneiss15
|
||||
Hamustra Scans
|
||||
HowITsDone
|
||||
Izzy
|
||||
Karol Kosek
|
||||
bittin
|
||||
Jacek
|
||||
Jacopo Gennaro Esposito
|
||||
Jasielprogramador
|
||||
Jean Mareilles
|
||||
Jean-Baptiste
|
||||
人工知能
|
||||
Karvjorm
|
||||
krkk
|
||||
Laura Ferraz
|
||||
Lucas da Costa
|
||||
Manan Jhaveri
|
||||
Marco
|
||||
BRBsoup
|
||||
Mattia
|
||||
Md. Al-Amin
|
||||
Michael Gangolf
|
||||
3DN1M
|
||||
Moi Toi
|
||||
DivideEtImpera
|
||||
Nicolas
|
||||
Nosnahc
|
||||
pbeckmann
|
||||
Peer Beckmann
|
||||
Piotr Strebski
|
||||
Piotr Zet
|
||||
Quang Nguyen
|
||||
Ratnesh
|
||||
Reza
|
||||
Rohan Babbar
|
||||
Ronak Upadhyay
|
||||
Rose Liverman
|
||||
SKULD
|
||||
Salem Malus
|
||||
Samarth Asthan
|
||||
Shailendra Maurya
|
||||
Simone Dotto
|
||||
Subhashish Anand
|
||||
darkodo
|
||||
TenTraicion
|
||||
Titas Pažereckas
|
||||
Tom Sawyer
|
||||
atakujonc
|
||||
Tony C
|
||||
Tymofii Lytvynenko
|
||||
Tjipke van der Heide
|
||||
Vancha March
|
||||
Yevgeny M
|
||||
Yusril A
|
||||
Avik Kundu
|
||||
diksha-2911
|
||||
gbonaspetti
|
||||
gittyboy-cell
|
||||
huang ivan
|
||||
lucafont2
|
||||
mtrmirez
|
||||
opsik
|
||||
polarhun
|
||||
pooyanazari
|
||||
psa-jforestier
|
||||
Robin
|
||||
sergio
|
||||
080502
|
||||
Marcus
|
||||
techwebpd
|
||||
Truestorybaby
|
||||
tygyh
|
||||
unstartdev
|
||||
wmilan 17
|
||||
luoyang3
|
||||
JaeBeom An
|
||||
JungHee Lee
|
||||
|
||||
293
app/src/main/res/values-ar/strings.xml
Normal file
293
app/src/main/res/values-ar/strings.xml
Normal file
@@ -0,0 +1,293 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="action_search">بحث</string>
|
||||
<string name="action_add">اضف</string>
|
||||
<string name="noGiftCards">اضغط على + الزر الإضافي لاضافة بطاقة, او استورد من ⋮ القائمة.</string>
|
||||
<string name="noMatchingGiftCards">لا نتائج. حاول تغيير كلمات البحث.</string>
|
||||
<string name="storeName">اسم</string>
|
||||
<string name="note">مذكرة</string>
|
||||
<string name="cardId">بطاقة شخصية</string>
|
||||
<string name="barcodeType">نوع الباركود</string>
|
||||
<string name="barcodeNoBarcode">لا يوجد باركود</string>
|
||||
<string name="noBarcode">لا يوجد باركود</string>
|
||||
<string name="star">اضف الي المفضلة</string>
|
||||
<string name="unstar">حذف من المفضلة</string>
|
||||
<string name="cancel">إلغاء</string>
|
||||
<string name="save">حفظ</string>
|
||||
<string name="edit">تعديل</string>
|
||||
<string name="delete">مسح</string>
|
||||
<string name="confirm">تأكيد</string>
|
||||
<string name="deleteConfirmation">مسح هذة البطاقة نهائيا؟</string>
|
||||
<string name="ok">حسنا</string>
|
||||
<string name="copy_to_clipboard">نسخ البطاقة الشخصية الى الحافظة</string>
|
||||
<string name="share">شارك</string>
|
||||
<string name="sendLabel">ارسل…</string>
|
||||
<string name="editCardTitle">عدل البطاقة</string>
|
||||
<string name="addCardTitle">اضف بطاقة</string>
|
||||
<string name="scanCardBarcode">مسح باركود</string>
|
||||
<string name="cardShortcut">اختصار البطاقة</string>
|
||||
<string name="noCardsMessage">اضف بطاقة أولا</string>
|
||||
<string name="card_ids_copied">البطاقة(ات) الشخصية المنسوخة</string>
|
||||
<string name="barcodeImageDescriptionWithType">صورة <xliff:g>%s</xliff:g> باركود</string>
|
||||
<string name="noStoreError">لا يوجد اسم مدخل</string>
|
||||
<string name="noCardIdError">لا يوجد بطاقة شخصية مدخلة</string>
|
||||
<string name="noCardExistsError">لا يمكن العثور على هذه البطاقة</string>
|
||||
<string name="failedParsingImportUriError">لا يمكن تحليل الرابط المستورد</string>
|
||||
<string name="importExport">استيراد/تصدير</string>
|
||||
<string name="importExportHelp">دعم بياناتك يسمح بنقلها إلى جهاز آخر.</string>
|
||||
<string name="importFailed">تعذر إجراء الاستيراد</string>
|
||||
<string name="exportSuccessfulTitle">متصدر</string>
|
||||
<string name="exportFailedTitle">فشل التصدير</string>
|
||||
<string name="exportFailed">لا يمكن عمل التصدير</string>
|
||||
<string name="exportOptionExplanation">ستتم كتابة البيانات في الموقع الذي تختاره.</string>
|
||||
<string name="importOptionFilesystemButton">من نظام الملفات</string>
|
||||
<string name="importOptionApplicationTitle">استخدم تطبيقًا آخر</string>
|
||||
<string name="importOptionApplicationExplanation">استخدم أي تطبيق أو مدير الملفات المفضل لديك لفتح ملف.</string>
|
||||
<string name="importOptionApplicationButton">استخدم تطبيقًا آخر</string>
|
||||
<string name="about">حول</string>
|
||||
<string name="app_copyright_old">بناء على Loyalty Card Keychain
|
||||
\nحقوق النشر © 2016-2020 Branden Archer</string>
|
||||
<string name="app_license">البرمجيات الحرة متروكة الحقوق, ترخيص +GPLv3</string>
|
||||
<string name="app_revision_fmt">معلومات المراجعة: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries">مكتبات الطرف الثالث الحرة: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="selectBarcodeTitle">اختار الباركود</string>
|
||||
<string name="enterBarcodeInstructions">أدخل بطاقة هوية ، واختر نوع الباركود أدناه ، أو \"لا يوجد باركود\".</string>
|
||||
<string name="copy_to_clipboard_toast">تم نسخ بطاقة الهوية إلى الحافظة</string>
|
||||
<string name="thumbnailDescription">صورة مصغرة</string>
|
||||
<string name="starImage">نجم مفضل</string>
|
||||
<string name="settings">اعدادات</string>
|
||||
<string name="settings_category_title_ui">واجهة المستخدم</string>
|
||||
<string name="settings_light_theme">فاتح</string>
|
||||
<string name="settings_dark_theme">داكن</string>
|
||||
<string name="settings_card_orientation">اتجاه الباركود</string>
|
||||
<string name="settings_portrait_orientation">الوضع الرأسي</string>
|
||||
<string name="settings_landscape_orientation">الوضع الأفقي</string>
|
||||
<string name="settings_theme">مظهر</string>
|
||||
<string name="settings_max_font_size_scale">اقصي. حجم الخط</string>
|
||||
<string name="settings_display_barcode_max_brightness">عرض مشرق علي الباركود</string>
|
||||
<string name="importSuccessful">تم استيراد البيانات</string>
|
||||
<string name="exportSuccessful">تم تصدير البيانات</string>
|
||||
<string name="enter_group_name">أدخل اسم المجموعة</string>
|
||||
<string name="group_edit">تعديل المجموعة</string>
|
||||
<string name="noGroups">اضغط زر + لإضافة مجموعات للتصنيف.</string>
|
||||
<string name="noGroupCards">هذه المجموعة فارغة</string>
|
||||
<string name="group_name_already_in_use">اسم المجموعة قيد الاستخدام بالفعل</string>
|
||||
<string name="group_name_is_empty">لا يمكن أن يكون اسم المجموعة فارغًا</string>
|
||||
<string name="group_updated">تم تحديث المجموعة</string>
|
||||
<string name="all">الكل</string>
|
||||
<string name="deleteConfirmationGroup">هل تريد حذف المجموعة؟</string>
|
||||
<string name="failedOpeningFileManager">قم بتثبيت مدير الملفات أولاً.</string>
|
||||
<string name="moveUp">تحرك لأعلى</string>
|
||||
<string name="addFromImage">حدد صورة من المعرض</string>
|
||||
<string name="balance">الرصيد</string>
|
||||
<string name="currency">العملة</string>
|
||||
<string name="points">نقاط</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> لا يبدو أنه رصيد صالح.</string>
|
||||
<string name="chooseImportType">استيراد البيانات من</string>
|
||||
<string name="app_loyalty_card_keychain">سلسلة مفاتيح بطاقة الولاء</string>
|
||||
<string name="privacy_policy">سياسة الخصوصية</string>
|
||||
<string name="accept">قبول</string>
|
||||
<string name="importCatima">الاستيراد من Catima</string>
|
||||
<string name="importCatimaMessage">حدد ملفك <i>catima.zip</i> تصدير من Catima للاستيراد.
|
||||
\nقم بإنشائه من قائمة الاستيراد / التصدير لتطبيق Catima آخر بالضغط على تصدير هناك أولاً.</string>
|
||||
<string name="importFidme">الاستيراد من FidMe</string>
|
||||
<string name="importFidmeMessage">حدد ملفك <i>fidme-export-request-xxxxxx.zip</i> تصدير من FidMe للاستيراد ، ثم حدد أنواع الباركود يدويًا بعد ذلك.
|
||||
\nقم بإنشائه من ملف تعريف FidMe الخاص بك عن طريق اختيار حماية البيانات ثم الضغط على استخراج بياناتي أولاً.</string>
|
||||
<string name="importStocardMessage">حدد ملفك <i>***-sync.zip</i> تصدير من Stocard للاستيراد.
|
||||
\nاحصل عليه عن طريق إرسال بريد إلكتروني إلى support@stocardapp.com لطلب تصدير بياناتك.</string>
|
||||
<string name="importVoucherVault">الاستيراد من Voucher Vault</string>
|
||||
<string name="importVoucherVaultMessage">حدد ملفك <i>vouchervault.json</i> تصدير من Voucher Vault للاستيراد.
|
||||
\nقم بإنشائه بالضغط على تصدير في Voucher Vault أولاً.</string>
|
||||
<string name="barcodeId">قيمة الباركود</string>
|
||||
<string name="sameAsCardId">نفس بطاقة الهوية</string>
|
||||
<string name="setBarcodeId">قم بتعيين قيمة الباركود</string>
|
||||
<string name="unsupportedBarcodeType">لا يمكن عرض نوع الباركود هذا. قد يكون مدعومًا في إصدار أحدث من التطبيق.</string>
|
||||
<string name="wrongValueForBarcodeType">القيمة غير صالحة لنوع الباركود المحدد</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">تم نسخ بطاقات الهوية إلى الحافظة</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">أريد مشاركة بعض البطاقات معك</string>
|
||||
<string name="frontImageDescription">الصورة الأمامية</string>
|
||||
<string name="backImageDescription">الصورة الخلفية</string>
|
||||
<string name="photos">الصور</string>
|
||||
<string name="setFrontImage">تعيين الصورة الأمامية</string>
|
||||
<string name="setBackImage">الصورة الخلفية</string>
|
||||
<string name="removeImage">إزالة الصورة</string>
|
||||
<string name="takePhoto">التقاط صورة</string>
|
||||
<string name="updateBarcodeQuestionTitle">هل تريد تحديث قيمة الباركود؟</string>
|
||||
<string name="updateBarcodeQuestionText">لقد قمت بتغيير بطاقة الهوية. هل تريد أيضًا تحديث الباركود لاستخدام نفس القيمة؟</string>
|
||||
<string name="yes">نعم</string>
|
||||
<string name="no">لا</string>
|
||||
<string name="passwordRequired">الرجاء إدخال كلمة المرور</string>
|
||||
<string name="exportPassword">قم بتعيين كلمة مرور لحماية التصدير (اختياري)</string>
|
||||
<string name="exportPasswordHint">أدخل كلمة المرور</string>
|
||||
<string name="turn_flashlight_on">قم بتشغيل المصباح</string>
|
||||
<string name="turn_flashlight_off">أطفئ المصباح</string>
|
||||
<string name="settings_locale">لغة</string>
|
||||
<string name="settings_system_locale">النظام</string>
|
||||
<string name="setIcon">تعيين رمز</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_pink_theme">زهري</string>
|
||||
<string name="settings_magenta_theme">أرجواني</string>
|
||||
<string name="settings_violet_theme">البنفسجي</string>
|
||||
<string name="settings_blue_theme">أزرق</string>
|
||||
<string name="settings_sky_blue_theme">أزرق سماوي</string>
|
||||
<string name="settings_green_theme">أخضر</string>
|
||||
<string name="settings_grey_theme">رمادي</string>
|
||||
<string name="settings_brown_theme">بني</string>
|
||||
<string name="app_contributors">أصبح ممكنًا بواسطة: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="sort">فرز</string>
|
||||
<string name="showMoreInfo">اظهر المعلومات</string>
|
||||
<string name="hideMoreInfo">إخفاء المعلومات</string>
|
||||
<string name="swipeToSwitchImages">امسح لتبديل الصور, اضغط لفترة طويلة لفتح الصورة في تطبيق المعرض</string>
|
||||
<string name="sort_by_balance">الرصيد</string>
|
||||
<string name="reverse">... بترتيب معكوس</string>
|
||||
<string name="sort_by">صنف حسب</string>
|
||||
<string name="settings_oled_dark">خلفية سوداء نقية لمظهر داكن</string>
|
||||
<string name="credits">الاعتمادات</string>
|
||||
<string name="source_repository">مستودع المصدر</string>
|
||||
<string name="and_data_usage">واستخدام البيانات</string>
|
||||
<string name="rate_this_app">قيم هذا التطبيق</string>
|
||||
<string name="translate_platform">على Weblate</string>
|
||||
<string name="shortcutSelectCard">اختر بطاقة</string>
|
||||
<string name="options">خيارات</string>
|
||||
<string name="starred">مميز بنجمة</string>
|
||||
<string name="set_scale">ضبط النطاق</string>
|
||||
<string name="include_if_asking_support">إذا كنت ترغب في طلب الدعم ، فقم بتضمين المعلومات التالية:</string>
|
||||
<string name="duplicateCard">كرر</string>
|
||||
<string name="archive">ضع الي الأرشيف</string>
|
||||
<string name="unarchive">أخرج من الأرشيف</string>
|
||||
<string name="archived">تمت أرشفة البطاقة</string>
|
||||
<string name="unarchived">البطاقة غير مؤرشفة</string>
|
||||
<string name="archiveList">أرشيف</string>
|
||||
<string name="failedLaunchingPhotoPicker">تعذر العثور على تطبيق معرض مدعوم</string>
|
||||
<string name="noGiftCardsGroup">انشئ بعض من البطاقات, و عيينهم لهذه المجموعة.</string>
|
||||
<string name="deleteTitle">مسح بطاقة</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="zero"><xliff:g>%d</xliff:g> محدد</item>
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> محددة</item>
|
||||
<item quantity="two"><xliff:g>%d</xliff:g> محدد</item>
|
||||
<item quantity="few"><xliff:g>%d</xliff:g> محدد</item>
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> محدد</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> محدد</item>
|
||||
</plurals>
|
||||
<string name="importing">جار الاستيراد…</string>
|
||||
<string name="exportName">تصدير</string>
|
||||
<string name="exporting">جار التصدير…</string>
|
||||
<string name="importSuccessfulTitle">مستورد</string>
|
||||
<string name="importFailedTitle">فشل بالاستيراد</string>
|
||||
<string name="sort_by_most_recently_used">الأكثر أستعمالا مؤخرا</string>
|
||||
<string name="license">رخصة</string>
|
||||
<string name="sort_by_name">اسم</string>
|
||||
<string name="version_history">تاريخ النسخة</string>
|
||||
<string name="action_hide_details">أخف التفاصيل</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="zero"><xliff:g>%1$d</xliff:g> بطاقة ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> بطاقة ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
<item quantity="two"><xliff:g>%1$d</xliff:g> بطاقة ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
<item quantity="few"><xliff:g>%1$d</xliff:g> بطاقات ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
<item quantity="many"><xliff:g>%1$d</xliff:g> بطاقات ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> بطاقات ( <xliff:g id="archivedCount">%2$d</xliff:g> مؤرشفة)</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="zero">مسح <xliff:g>%d</xliff:g> بطاقة</item>
|
||||
<item quantity="one">مسح <xliff:g>%d</xliff:g> بطاقة</item>
|
||||
<item quantity="two">مسح <xliff:g>%d</xliff:g> بطاقتين</item>
|
||||
<item quantity="few">مسح <xliff:g>%d</xliff:g> بطاقات</item>
|
||||
<item quantity="many">مسح <xliff:g>%d</xliff:g> بطاقات</item>
|
||||
<item quantity="other">مسح <xliff:g>%d</xliff:g> بطاقات</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="zero">مسح هذه <xliff:g>%d</xliff:g> البطاقة نهائيا؟</item>
|
||||
<item quantity="one">مسح هذه <xliff:g>%d</xliff:g> البطاقة نهائيا؟</item>
|
||||
<item quantity="two">مسح هذه <xliff:g>%d</xliff:g> البطاقتين نهائيا؟</item>
|
||||
<item quantity="few">مسح هذه <xliff:g>%d</xliff:g> البطاقات نهائيا؟</item>
|
||||
<item quantity="many">مسح هذه <xliff:g>%d</xliff:g> البطاقات نهائيا؟</item>
|
||||
<item quantity="other">مسح هذه <xliff:g>%d</xliff:g> البطاقات نهائيا؟</item>
|
||||
</plurals>
|
||||
<string name="importOptionFilesystemTitle">الاستيراد من نظام الملفات</string>
|
||||
<string name="importOptionFilesystemExplanation">اختر ملفًا محددًا من نظام الملفات.</string>
|
||||
<string name="about_title_fmt">حول <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">نسخة: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="settings_system_theme">نظام</string>
|
||||
<string name="settings_lock_on_opening_orientation">قفل على الاتجاه عند فتح البطاقة</string>
|
||||
<string name="app_resources">موارد الطرف الثالث الحرة: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="settings_follow_system_orientation">نظام المتابعة</string>
|
||||
<string name="groups">مجموعات</string>
|
||||
<string name="barcode">باركود</string>
|
||||
<string name="settings_keep_screen_on">حافظ على الشاشة قيد التشغيل</string>
|
||||
<string name="intent_import_card_from_url_share_text">اريد مشاركة بطاقة معك</string>
|
||||
<string name="groupsList">مجموعات: <xliff:g>%s</xliff:g></string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">منع قفل الشاشة</string>
|
||||
<string name="leaveWithoutSaveTitle">خروج</string>
|
||||
<string name="editGroup">مجموعة التعديل: <xliff:g>%s</xliff:g></string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="zero"><xliff:g>%d</xliff:g> بطاقة</item>
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> بطاقة</item>
|
||||
<item quantity="two"><xliff:g>%d</xliff:g> بطاقة</item>
|
||||
<item quantity="few"><xliff:g>%d</xliff:g> بطاقات</item>
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> بطاقات</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> بطاقات</item>
|
||||
</plurals>
|
||||
<string name="moveDown">تحرك لأسفل</string>
|
||||
<string name="leaveWithoutSaveConfirmation">المغادرة دون حفظ؟</string>
|
||||
<string name="addManually">أدخل بطاقة الهوية يدويًا</string>
|
||||
<string name="moveBarcodeToTopOfScreen">انقل الباركود إلى أعلى الشاشة</string>
|
||||
<string name="balanceSentence">الرصيد: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">تنتهي: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentenceExpired">منتهي الصلاحية: <xliff:g>%s</xliff:g></string>
|
||||
<string name="moveBarcodeToCenterOfScreen">قم بتوسيط الرمز الشريطي على الشاشة</string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="zero"><xliff:g>%s</xliff:g> نقطة</item>
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> نقطة</item>
|
||||
<item quantity="two"><xliff:g>%s</xliff:g> نقطة</item>
|
||||
<item quantity="few"><xliff:g>%s</xliff:g> نقطات</item>
|
||||
<item quantity="many"><xliff:g>%s</xliff:g> نقطات</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> نقطات</item>
|
||||
</plurals>
|
||||
<string name="card">بطاقة</string>
|
||||
<string name="selectColor">إختر لون</string>
|
||||
<string name="editBarcode">تعديل الباركود</string>
|
||||
<string name="expiryDate">تاريخ انتهاء الصلاحية</string>
|
||||
<string name="never">أبداً</string>
|
||||
<string name="chooseExpiryDate">اختر تاريخ انتهاء الصلاحية</string>
|
||||
<string name="errorReadingImage">لا يمكن قراءة الصورة</string>
|
||||
<string name="noBarcodeFound">لم يتم العثور على باركود</string>
|
||||
<string name="on_github">على GitHub</string>
|
||||
<string name="report_error">الإبلاغ عن خطأ</string>
|
||||
<string name="sort_by_expiry">انقضاء</string>
|
||||
<string name="noUnarchivedCardsMessage">لا توجد بطاقات غير مؤرشفة موجودة</string>
|
||||
<string name="importLoyaltyCardKeychain">الاستيراد من Loyalty Card Keychain</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Copyright © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">حدد ملفك <i>LoyaltyCardKeychain.csv</i> التصدير من Loyalty Card Keychain للاستيراد.
|
||||
\nقم بإنشائه من قائمة الاستيراد / التصدير في Loyalty Card Keychain بالضغط على تصدير هناك أولاً.</string>
|
||||
<string name="importStocard">الاستيراد من Stocard</string>
|
||||
<string name="privacy_policy_popup_text">إشعار سياسة الخصوصية (مطلوب من قبل بعض متاجر التطبيقات):
|
||||
\n
|
||||
\nلا يتم جمع أي بيانات على الإطلاق ، والتي يمكن لأي شخص تأكيدها لأن تطبيقنا هو برنامج حر.</string>
|
||||
<string name="failedGeneratingShareURL">تعذر إنشاء عنوان URL قابل للمشاركة. الرجاء الإبلاغ عن هذا.</string>
|
||||
<string name="help_translate_this_app">ساعد في ترجمة هذا التطبيق</string>
|
||||
<string name="action_show_details">اظهر التفاصيل</string>
|
||||
<string name="on_google_play">على Google Play</string>
|
||||
<string name="settings_theme_color">لون المظهر</string>
|
||||
<string name="previousCard">السابق</string>
|
||||
<string name="nextCard">التالي</string>
|
||||
<string name="failedToRetrieveImageFile">فشل في استخراج ملف الصورة</string>
|
||||
<string name="barcodeLongPressMessage">يمكن فتح صور فقط في تطبيق معرض الصور</string>
|
||||
<string name="failedToOpenUrl">ثبت متصفح ويب أولاً</string>
|
||||
<string name="welcome">مرحبا بك في كاتيما</string>
|
||||
<string name="updateBalanceTitle">كم أنفقت؟</string>
|
||||
<string name="currentBalanceSentence">الرصيد الحالي: <xliff:g> %s </xliff:g></string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="zero">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقة)</item>
|
||||
<item quantity="one">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقة)</item>
|
||||
<item quantity="two">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقتين)</item>
|
||||
<item quantity="few">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقات)</item>
|
||||
<item quantity="many">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقات)</item>
|
||||
<item quantity="other">عرض الأرشيف (<xliff:g>%1$d</xliff:g> بطاقات)</item>
|
||||
</plurals>
|
||||
<string name="importCards">استيراد البطاقات</string>
|
||||
<string name="newBalanceSentence">الرصيد الجديد: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">تعذر الوصول إلى الكاميرا</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">لمسح الباركود، ستحتاج Catima إلى الوصول إلى الكاميرا. اضغط هنا لتغيير إعدادات الأذونات.</string>
|
||||
<string name="updateBalance">تحديث الرصيد</string>
|
||||
<string name="updateBalanceHint">أدخل المبلغ</string>
|
||||
</resources>
|
||||
2
app/src/main/res/values-ars/strings.xml
Normal file
2
app/src/main/res/values-ars/strings.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -10,7 +10,7 @@
|
||||
<string name="cancel">Отказ</string>
|
||||
<string name="unstar">Премахва от любими</string>
|
||||
<string name="star">Добавя към любими</string>
|
||||
<string name="noBarcode">Без щрихкод</string>
|
||||
<string name="noBarcode">Липсва щрихкод</string>
|
||||
<string name="barcodeNoBarcode">Липсва щрихкод</string>
|
||||
<string name="barcodeType">Вид на щрихкод</string>
|
||||
<string name="cardId">Идентификатор на карта</string>
|
||||
@@ -34,7 +34,6 @@
|
||||
<string name="setFrontImage">Снимка на предната страна</string>
|
||||
<string name="photos">Снимки</string>
|
||||
<string name="importOptionApplicationExplanation">Изберете файл на друго приложение.</string>
|
||||
<string name="noExternalStoragePermissionError">Разрешете достъп до хранилището, за да работи внасянето и изнасянето</string>
|
||||
<string name="noCardExistsError">Картата не е намерена</string>
|
||||
<string name="updateBarcodeQuestionText">Идентификаторът е променен. Желаете ли с неговата стойност да бъде променен и щрихкодът\?</string>
|
||||
<string name="updateBarcodeQuestionTitle">Обновяване на щрихкода\?</string>
|
||||
@@ -158,7 +157,7 @@
|
||||
<string name="importLoyaltyCardKeychainMessage">Изберете файла <i>LoyaltyCardKeychain.csv</i>, предварително изнесен от Loyalty Card Keychain.
|
||||
\nСъздайте такъв файл от меню Внасяне/изнасяне от друго устройство с Loyalty Card Keychain като изберете Изнасяне.</string>
|
||||
<string name="failedParsingImportUriError">Препратката не може да бъде анализирана за внасяне</string>
|
||||
<string name="failedGeneratingShareURL">Грешка при създаване на адрес за споделяне. Изпратете доклад за дефект.</string>
|
||||
<string name="failedGeneratingShareURL">Не може да бъде генериран адрес за споделяне. Изпратете доклад за дефект.</string>
|
||||
<string name="deleteTitle">Премахване на карта</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Изтриване на <xliff:g>%d</xliff:g> карта</item>
|
||||
@@ -184,7 +183,7 @@
|
||||
<string name="settings_locale">Език</string>
|
||||
<string name="noGroupCards">Групата е празна</string>
|
||||
<string name="barcodeImageDescriptionWithType">Изображение на щрихкод от вид <xliff:g>%s</xliff:g></string>
|
||||
<string name="swipeToSwitchImages">Плъзване или задържане за смяна на изображения</string>
|
||||
<string name="swipeToSwitchImages">За да размените изображенията - плъзнете, а за да ги отворите в галерията - задръжте</string>
|
||||
<string name="sort_by">Сортиране по</string>
|
||||
<string name="reverse">…в обратен ред</string>
|
||||
<string name="sort_by_balance">Наличност</string>
|
||||
@@ -240,4 +239,33 @@
|
||||
<string name="unarchived">Карта е извадена от архива</string>
|
||||
<string name="archiveList">Архив</string>
|
||||
<string name="noUnarchivedCardsMessage">Няма карти извън архива</string>
|
||||
<string name="failedLaunchingPhotoPicker">Не е намерено поддържано приложение за галерия</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> карта (<xliff:g id="archivedCount">%2$d</xliff:g> архивирана)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> карти (<xliff:g id="archivedCount">%2$d</xliff:g> архивирани)</item>
|
||||
</plurals>
|
||||
<string name="previousCard">Предишна</string>
|
||||
<string name="nextCard">Следваща</string>
|
||||
<string name="failedToOpenUrl">Първо инсталирайте уеб браузър</string>
|
||||
<string name="welcome">Добре дошли при Катима</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Преглед на архива (<xliff:g>%1$d</xliff:g> карта)</item>
|
||||
<item quantity="other">Преглед на архива (<xliff:g>%1$d</xliff:g> карти)</item>
|
||||
</plurals>
|
||||
<string name="barcodeLongPressMessage">В приложението галерия могат да бъдат отваряни само изображения</string>
|
||||
<string name="failedToRetrieveImageFile">Не е възможно извличане на изображение</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">За да сканирате щрихкодове с Catima е необходим достъп до камерата. За да промените разрешението докоснете тук.</string>
|
||||
<string name="updateBalanceTitle">Каква е промяната\?</string>
|
||||
<string name="updateBalanceHint">Въведете стойност</string>
|
||||
<string name="newBalanceSentence">Нов баланс: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">Камерата е недостъпна</string>
|
||||
<string name="currentBalanceSentence">Текущ баланс: <xliff:g>%s</xliff:g></string>
|
||||
<string name="updateBalance">Обновяване на баланса</string>
|
||||
<string name="importCards">Внасяне на карти</string>
|
||||
<string name="storageReadPermissionRequired">За това действие е необходимо разрешение за четене на хранилището…</string>
|
||||
<string name="cameraPermissionRequired">За това действие е необходимо разрешение за достъп до камерата…</string>
|
||||
<string name="validFromDate">Валидна от</string>
|
||||
<string name="anyDate">Без значение от датата</string>
|
||||
<string name="validFromSentence">Валидна от: <xliff:g>%s</xliff:g></string>
|
||||
<string name="chooseValidFromDate">Изберете датата, от която е валидна</string>
|
||||
</resources>
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="save">সংরক্ষণ</string>
|
||||
<string name="cancel">বাতিল</string>
|
||||
<string name="unstar">তারা মুক্ত</string>
|
||||
<string name="star">তারা</string>
|
||||
<string name="barcodeNoBarcode">বারকোড না বারকোড</string>
|
||||
<string name="barcodeNoBarcode">কোনো বারকোড নেই</string>
|
||||
<string name="barcodeType">বারকোড ধরন</string>
|
||||
<string name="note">বিঃদ্রঃ</string>
|
||||
<string name="storeName">দোকানের নাম</string>
|
||||
@@ -38,8 +38,8 @@
|
||||
<string name="wrongValueForBarcodeType">বারকোড টাইপের জন্য ভুল মান</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ক্লিপবোর্ড একাধিক টোস্টে অনুলিপি করুন</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">url থেকে ইন্টেন্ট ইম্পোর্ট কার্ড একাধিক টেক্সট শেয়ার করে</string>
|
||||
<string name="frontImageDescription">সামনের চিত্রের বর্ণনা</string>
|
||||
<string name="backImageDescription">পিছনের চিত্রের বর্ণনা</string>
|
||||
<string name="frontImageDescription">সামনের চিত্র</string>
|
||||
<string name="backImageDescription">পিছনের চিত্র</string>
|
||||
<string name="photos">ছবি</string>
|
||||
<string name="setFrontImage">সদর ছবি স্থাপন</string>
|
||||
<string name="setBackImage">পিছনের ছবি স্থাপন</string>
|
||||
@@ -71,17 +71,34 @@
|
||||
<string name="sort_by_expiry">মেয়াদ শেষ করে সাজান</string>
|
||||
<string name="reverse">বিপরীত</string>
|
||||
<string name="sort_by">ক্রমানুসার</string>
|
||||
<string name="noCardExistsError">কোন কার্ড নেই ত্রুটি</string>
|
||||
<string name="noCardExistsError">কার্ডটি পাওয়া যায়নি</string>
|
||||
<string name="noStoreError">স্টোরেজ ত্রুটি নেই</string>
|
||||
<string name="card_ids_copied">কার্ড আইডি কপি করা হয়েছে</string>
|
||||
<string name="card_ids_copied">আইডি কপি করা হয়েছে</string>
|
||||
<string name="noCardsMessage">কোন কার্ড বার্তা নেই</string>
|
||||
<string name="addCardTitle">কার্ডের শিরোনাম যোগ করুন</string>
|
||||
<string name="editCardTitle">কার্ডের শিরোনাম সম্পাদনা করুন</string>
|
||||
<string name="sendLabel">লেবেল পাঠান</string>
|
||||
<string name="sendLabel">পাঠান…</string>
|
||||
<string name="share">ভাগ</string>
|
||||
<string name="copy_to_clipboard">নকল করুন ক্লিপবোর্ড এ</string>
|
||||
<string name="deleteConfirmation">নিশ্চিতকরণ মুছে দিন</string>
|
||||
<string name="confirm">নিশ্চিত করুন</string>
|
||||
<string name="delete">মুছে ফেলুন</string>
|
||||
<string name="edit">সম্পাদনা</string>
|
||||
<string name="action_search">খুঁজুন</string>
|
||||
<string name="card">কার্ড</string>
|
||||
<string name="currency">মুদ্রা</string>
|
||||
<string name="cardId">কার্ড আইডি</string>
|
||||
<string name="noBarcode">বারকোড নেই</string>
|
||||
<string name="deleteTitle">কার্ড ডিলিট করুন</string>
|
||||
<string name="ok">ঠিক আছে</string>
|
||||
<string name="about">সম্পর্কিত</string>
|
||||
<string name="debug_version_fmt">সংস্করণ:
|
||||
\n<xliff:g id="version">
|
||||
\n%s</xliff:g></string>
|
||||
<string name="importOptionApplicationButton">অন্য অ্যাপ ব্যাবহার করুন</string>
|
||||
<string name="moveUp">উপরে উঠান</string>
|
||||
<string name="moveDown">নিচে নামান</string>
|
||||
<string name="barcode">বারকোড</string>
|
||||
<string name="expiryDate">মেয়াদোত্তীর্ণ তারিখ</string>
|
||||
<string name="noBarcodeFound">কোনো বারকোড পাওয়া যায়নি</string>
|
||||
</resources>
|
||||
55
app/src/main/res/values-bn/strings.xml
Normal file
55
app/src/main/res/values-bn/strings.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="settings_locale">ভাষা</string>
|
||||
<string name="action_search">খুঁজুন</string>
|
||||
<string name="settings_pink_theme">গুলাপি</string>
|
||||
<string name="settings_blue_theme">নীল</string>
|
||||
<string name="settings_green_theme">সবুজ</string>
|
||||
<string name="settings_brown_theme">বাদামি</string>
|
||||
<string name="save">সংরক্ষণ</string>
|
||||
<string name="cardId">কার্ড আইডি</string>
|
||||
<string name="barcodeType">বারকোডের ধরন</string>
|
||||
<string name="about">সম্পর্কিত</string>
|
||||
<string name="card">কার্ড</string>
|
||||
<string name="yes">হ্যাঁ</string>
|
||||
<string name="settings_grey_theme">ধূসর</string>
|
||||
<string name="ok">ঠিক আছে</string>
|
||||
<string name="sendLabel">পাঠান…</string>
|
||||
<string name="sort_by_name">নাম</string>
|
||||
<string name="previousCard">পূর্ববর্তী</string>
|
||||
<string name="all">সকল</string>
|
||||
<string name="barcode">বারকোড</string>
|
||||
<string name="never">কখনো না</string>
|
||||
<string name="currency">মুদ্রা</string>
|
||||
<string name="settings_violet_theme">বেগুনি</string>
|
||||
<string name="no">না</string>
|
||||
<string name="nextCard">পরবর্তী</string>
|
||||
<string name="action_add">যুক্ত করুন</string>
|
||||
<string name="noGiftCardsGroup">কিছু কার্ড তৈরি করুন এবং তারপর সেগুলিকে এখানে গ্রুপে বরাদ্দ করুন।</string>
|
||||
<string name="noMatchingGiftCards">কোন ফলাফল নেই. আপনার অনুসন্ধান পরিবর্তন করার চেষ্টা করুন.</string>
|
||||
<string name="storeName">নাম</string>
|
||||
<string name="note">বিঃদ্রঃ</string>
|
||||
<string name="star">ফেভারিটে যোগ করুন</string>
|
||||
<string name="barcodeNoBarcode">কোন বারকোড নেই</string>
|
||||
<string name="noBarcode">বারকোড নেই</string>
|
||||
<string name="unstar">পছন্দের তালিকা থেকে অপসারণ</string>
|
||||
<string name="cancel">বাতিল করুন</string>
|
||||
<string name="edit">সম্পাদনা করুন</string>
|
||||
<string name="delete">মুছে ফেলা</string>
|
||||
<string name="confirm">নিশ্চিত করুন</string>
|
||||
<string name="deleteConfirmation">এই কার্ডটি স্থায়ীভাবে মুছবেন\?</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">এই <xliff:g>%d</xliff:g> কার্ডটি স্থায়ীভাবে মুছবেন\?</item>
|
||||
<item quantity="other">এই <xliff:g>%d</xliff:g> কার্ডগুলিকে স্থায়ীভাবে মুছবেন\?</item>
|
||||
</plurals>
|
||||
<string name="copy_to_clipboard">ক্লিপবোর্ডে আইডি কপি করুন</string>
|
||||
<string name="share">শেয়ার করুন</string>
|
||||
<string name="editCardTitle">কার্ড সম্পাদনা করুন</string>
|
||||
<string name="addCardTitle">কার্ড যোগ করুন</string>
|
||||
<string name="scanCardBarcode">বারকোড স্ক্যান করুন</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> কার্ড মুছুন</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> কার্ডগুলো মুছুন</item>
|
||||
</plurals>
|
||||
<string name="deleteTitle">কার্ড মুছুন</string>
|
||||
</resources>
|
||||
@@ -4,11 +4,11 @@
|
||||
<string name="cancel">Odustani</string>
|
||||
<string name="unstar">Ukloni sve omiljene</string>
|
||||
<string name="star">Omiljene</string>
|
||||
<string name="barcodeNoBarcode">Ova kartica nema barkode</string>
|
||||
<string name="barcodeNoBarcode">Ne postoji barkod</string>
|
||||
<string name="barcodeType">Barcode tip</string>
|
||||
<string name="note">Bilježnica</string>
|
||||
<string name="storeName">Ime</string>
|
||||
<string name="noMatchingGiftCards">Nisam našao ništa. Pokušaj promijeniti pretragu.</string>
|
||||
<string name="noMatchingGiftCards">Nema rezultata. Pokušaj promijeniti pretragu.</string>
|
||||
<string name="noGiftCards">Kliknite + Plus dugme da dodate kartu ili uvozite nešto iz menija prvo.</string>
|
||||
<string name="action_add">Dodaj</string>
|
||||
<string name="all">Sve</string>
|
||||
@@ -71,9 +71,9 @@
|
||||
<string name="sort_by_expiry">Sajam</string>
|
||||
<string name="reverse">Rikverc</string>
|
||||
<string name="sort_by">Sortiraj</string>
|
||||
<string name="noCardExistsError">Nisam mogao pronaći karticu</string>
|
||||
<string name="noCardExistsError">Nisam mogao pronaći tu karticu</string>
|
||||
<string name="noStoreError">Nije uneseno ime</string>
|
||||
<string name="card_ids_copied">Kopiran ID kartice(s)</string>
|
||||
<string name="card_ids_copied">Kopiran ID/ovi</string>
|
||||
<string name="noCardsMessage">Dodaj prvo kartu</string>
|
||||
<string name="addCardTitle">Dodaj Kartu</string>
|
||||
<string name="editCardTitle">Izmijeni Karticu</string>
|
||||
@@ -84,4 +84,33 @@
|
||||
<string name="confirm">Potvrdi</string>
|
||||
<string name="delete">Obriši</string>
|
||||
<string name="edit">Izmijeni</string>
|
||||
<string name="action_search">Traži</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cardId">ID kartice</string>
|
||||
<string name="exportFailed">Nisam uspio izvršiti izvoz</string>
|
||||
<string name="app_copyright_old">Bazirano na Loyalty Card privjesku
|
||||
\ncopyright © 2016-2020 Branden Archer</string>
|
||||
<string name="noGiftCardsGroup">Kreirajte kartice, i dodajte ih ovdje u grupu.</string>
|
||||
<string name="importExportHelp">Backupovanje vaših podataka omogućava njihov prenos na drugi uređaj.</string>
|
||||
<string name="importSuccessfulTitle">Uvezeno</string>
|
||||
<string name="exportFailedTitle">Izvoz neuspješan</string>
|
||||
<string name="scanCardBarcode">Skeniraj barkod</string>
|
||||
<string name="cardShortcut">Prečica kartice</string>
|
||||
<string name="noCardIdError">ID nije unesen</string>
|
||||
<string name="failedParsingImportUriError">Nisam uspio parsirati URI za uvoz</string>
|
||||
<string name="importExport">Uvoz/Izvoz</string>
|
||||
<string name="exportName">Izvoz</string>
|
||||
<string name="importFailedTitle">Uvoz neuspješan</string>
|
||||
<string name="importFailed">Nisam uspio odraditi uvoz</string>
|
||||
<string name="exportSuccessfulTitle">Izvezeno</string>
|
||||
<string name="importing">Uvozim…</string>
|
||||
<string name="exporting">Izvozim…</string>
|
||||
<string name="exportOptionExplanation">Ovi podaci će biti zapisani na lokaciju po Vašoj želji.</string>
|
||||
<string name="importOptionFilesystemTitle">Uvoz iz file sistema</string>
|
||||
<string name="importOptionFilesystemExplanation">Izaberite specifični file iz file sistema.</string>
|
||||
<string name="importOptionFilesystemButton">Iz file sistema</string>
|
||||
<string name="importOptionApplicationTitle">Koristi drugu aplikaciju</string>
|
||||
<string name="importOptionApplicationExplanation">Koristi bilo koju aplikaciju ili Vašu omiljenu aplikaciju da bi otvorili file.</string>
|
||||
<string name="importOptionApplicationButton">Koristi drugu aplikaciju</string>
|
||||
<string name="about">O</string>
|
||||
</resources>
|
||||
16
app/src/main/res/values-ca/strings.xml
Normal file
16
app/src/main/res/values-ca/strings.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="groups">Grups</string>
|
||||
<string name="action_add">Afegeix</string>
|
||||
<string name="save">Desa</string>
|
||||
<string name="edit">Edita</string>
|
||||
<string name="delete">Elimina</string>
|
||||
<string name="confirm">Confirma</string>
|
||||
<string name="ok">D\'acord</string>
|
||||
<string name="importExport">Importa/Exporta</string>
|
||||
<string name="exportName">Exporta</string>
|
||||
<string name="action_search">Cerca</string>
|
||||
<string name="deleteTitle">Elimina la targeta</string>
|
||||
<string name="welcome">Benvingut a Catima</string>
|
||||
<string name="noGiftCards">Cliqueu el botó + més per afegir una targeta, o importeu-ne des del ⋮ menú.</string>
|
||||
</resources>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="action_add">Přidat</string>
|
||||
<string name="noGiftCards">Klepnutím na tlačítko + plus přidáte kartu nebo ji nejprve importujete z nabídky ⋮.</string>
|
||||
<string name="noGiftCards">Klepněte na tlačítko + plus pro přidání karty nebo naimportujete karty z nabídky ⋮.</string>
|
||||
<string name="storeName">Název</string>
|
||||
<string name="note">Poznámka</string>
|
||||
<string name="cardId">ID karty</string>
|
||||
@@ -13,56 +13,55 @@
|
||||
<string name="ok">Ano</string>
|
||||
<string name="copy_to_clipboard">Kopírovat ID do schránky</string>
|
||||
<string name="sendLabel">Odeslat…</string>
|
||||
<string name="editCardTitle">Editovat věrnostní kartu</string>
|
||||
<string name="addCardTitle">Přidat věrnostní kartu</string>
|
||||
<string name="editCardTitle">Editovat kartu</string>
|
||||
<string name="addCardTitle">Přidat kartu</string>
|
||||
<string name="scanCardBarcode">Skenování čárového kódu</string>
|
||||
<string name="noStoreError">Zadáno žádné jméno</string>
|
||||
<string name="noCardIdError">ID nezadáno</string>
|
||||
<string name="noStoreError">Nezadáno žádné jméno</string>
|
||||
<string name="noCardIdError">Nezadáno ID</string>
|
||||
<string name="importExport">Import/Export</string>
|
||||
<string name="exportName">Export</string>
|
||||
<string name="importExportHelp">Zálohování dat vám umožní přesunout je do jiného zařízení.</string>
|
||||
<string name="importSuccessfulTitle">Importováno</string>
|
||||
<string name="importFailedTitle">Import selhal</string>
|
||||
<string name="importFailed">Nelze provést import</string>
|
||||
<string name="importFailed">Import nelze provést</string>
|
||||
<string name="exportSuccessfulTitle">Exportováno</string>
|
||||
<string name="exportFailedTitle">Export selhal</string>
|
||||
<string name="exportFailed">Nelze provést export</string>
|
||||
<string name="exportFailed">Export nelze provést</string>
|
||||
<string name="importing">Importuji…</string>
|
||||
<string name="exporting">Exportuji…</string>
|
||||
<string name="noExternalStoragePermissionError">Udělit oprávnění přístupu k externímu úložišti pro import nebo export dat</string>
|
||||
<string name="importOptionFilesystemTitle">Import ze souborového systému</string>
|
||||
<string name="importOptionFilesystemExplanation">Vyberte konkrétní soubor v uložišti.</string>
|
||||
<string name="importOptionFilesystemExplanation">Vyberte konkrétní soubor v úložišti.</string>
|
||||
<string name="importOptionFilesystemButton">Ze souborového systému</string>
|
||||
<string name="importOptionApplicationTitle">Použijte jinou aplikaci</string>
|
||||
<string name="importOptionApplicationExplanation">K otevření souboru použijte libovolnou aplikaci nebo svého oblíbeného správce souborů.</string>
|
||||
<string name="importOptionApplicationButton">Použijte jinou aplikaci</string>
|
||||
<string name="importOptionApplicationTitle">Použitím jiné aplikace</string>
|
||||
<string name="importOptionApplicationExplanation">K otevření souboru použijte libovolnou aplikaci nebo svého oblíbeného správce souborů.</string>
|
||||
<string name="importOptionApplicationButton">Použít jinou aplikaci</string>
|
||||
<string name="about">O aplikaci</string>
|
||||
<string name="app_license">Copyleftovaný svobodný software s licencí GPLv3+</string>
|
||||
<string name="app_license">Copyleftovaný svobodný software s licencí GPLv3+</string>
|
||||
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informace o revizi: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="selectBarcodeTitle">Vyberte čárový kód</string>
|
||||
<string name="copy_to_clipboard_toast">ID zkopírované do schránky</string>
|
||||
<string name="copy_to_clipboard_toast">ID zkopírováno do schránky</string>
|
||||
<string name="deleteTitle">Smazat kartu</string>
|
||||
<string name="deleteConfirmation">Opravdu chcete smazat tuto věrnostní kartu?</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Střed čárového kódu na obrazovce</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Přesuňte čárový kód do horní části obrazovky</string>
|
||||
<string name="deleteConfirmation">Opravdu chcete smazat tuto kartu\?</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Vycentrovat čárový kód na obrazovce</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Přesunout čárový kód do horní části obrazovky</string>
|
||||
<string name="chooseExpiryDate">Zvolte datum vypršení platnosti</string>
|
||||
<string name="never">Nikdy</string>
|
||||
<string name="expiryDate">Platnost</string>
|
||||
<string name="expiryDate">Vypršení platnosti</string>
|
||||
<string name="editBarcode">Upravit čárový kód</string>
|
||||
<string name="barcode">Kód</string>
|
||||
<string name="app_resources">Svobodné zdroje třetích stran: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Svobodné knihovny třetích stran: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_copyright_old">Na základě Loyalty Card Keychain
|
||||
<string name="app_copyright_old">Založeno na Loyalty Card Keychain
|
||||
\ncopyright © 2016–2020 Branden Archer</string>
|
||||
<string name="exportOptionExplanation">Data budou zapsána na místo podle vašeho výběru.</string>
|
||||
<string name="failedParsingImportUriError">Nelze analyzovat import URI</string>
|
||||
<string name="noCardExistsError">Kartu nelze najít</string>
|
||||
<string name="failedParsingImportUriError">Nelze analyzovat importovanou URI</string>
|
||||
<string name="noCardExistsError">Takovou kartu nelze najít</string>
|
||||
<string name="noCardsMessage">Nejprve přidejte kartu</string>
|
||||
<string name="cardShortcut">Zástupce Karty</string>
|
||||
<string name="share">Podíl</string>
|
||||
<string name="unstar">Odebrat z oblíbených</string>
|
||||
<string name="cardShortcut">Zástupce karty</string>
|
||||
<string name="share">Sdílet</string>
|
||||
<string name="unstar">Odebrat z oblíbených</string>
|
||||
<string name="star">Přidat do oblíbených</string>
|
||||
<string name="noBarcode">Žádný čárový kód</string>
|
||||
<string name="barcodeNoBarcode">Tato karta nemá čárový kód</string>
|
||||
@@ -70,25 +69,25 @@
|
||||
<string name="noMatchingGiftCards">Nic nenalezeno. Zkuste změnit vyhledávání.</string>
|
||||
<string name="action_search">Vyhledávání</string>
|
||||
<string name="thumbnailDescription">Miniatura</string>
|
||||
<string name="card_ids_copied">Zkopírované ID</string>
|
||||
<string name="card_ids_copied">ID zkopírováno</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Opravdu chcete kartu <xliff:g>%d</xliff:g> trvale odstranit\?</item>
|
||||
<item quantity="few">Opravdu chcete karty <xliff:g>%d</xliff:g> trvale odstranit\?</item>
|
||||
<item quantity="other">Opravdu chcete karty <xliff:g>%d</xliff:g> trvale odstranit\?</item>
|
||||
<item quantity="one">Opravdu chcete trvale odstranit <xliff:g>%d</xliff:g> kartu\?</item>
|
||||
<item quantity="few">Opravdu chcete trvale odstranit <xliff:g>%d</xliff:g> karty\?</item>
|
||||
<item quantity="other">Opravdu chcete trvale odstranit <xliff:g>%d</xliff:g> karet\?</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Odstranit kartu <xliff:g>%d</xliff:g></item>
|
||||
<item quantity="few">Odstranit karty <xliff:g>%d</xliff:g></item>
|
||||
<item quantity="other">Odstranit karty <xliff:g>%d</xliff:g></item>
|
||||
<item quantity="one">Odstranit <xliff:g>%d</xliff:g> kartu</item>
|
||||
<item quantity="few">Odstranit <xliff:g>%d</xliff:g> karty</item>
|
||||
<item quantity="other">Odstranit <xliff:g>%d</xliff:g> karet</item>
|
||||
</plurals>
|
||||
<string name="importSuccessful">Data importována</string>
|
||||
<string name="intent_import_card_from_url_share_text">Chci s Vámi sdílet kartu</string>
|
||||
<string name="intent_import_card_from_url_share_text">Chci s Vámi sdílet kartu</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Bránit uzamykání obrazovky</string>
|
||||
<string name="settings_keep_screen_on">Udržovat obrazovku zapnutou</string>
|
||||
<string name="settings_max_font_size_scale">Maximální velikost písma</string>
|
||||
<string name="settings_dark_theme">Tmavý</string>
|
||||
<string name="settings_light_theme">Světlý</string>
|
||||
<string name="settings_system_theme">Systém</string>
|
||||
<string name="settings_system_theme">Podle systému</string>
|
||||
<string name="settings_theme">Vzhled</string>
|
||||
<string name="settings_category_title_ui">Uživatelské rozhraní</string>
|
||||
<string name="settings">Nastavení</string>
|
||||
@@ -98,7 +97,7 @@
|
||||
<string name="expiryStateSentence">Platí do: <xliff:g>%s</xliff:g></string>
|
||||
<string name="moveDown">Přesunout dolů</string>
|
||||
<string name="moveUp">Přesunout nahoru</string>
|
||||
<string name="enterBarcodeInstructions">Zadejte ID a níže vyberte typ čárového kódu nebo \"Tato karta nemá čárový kód\".</string>
|
||||
<string name="enterBarcodeInstructions">Zadejte ID a níže vyberte typ čárového kódu nebo „Tato karta nemá čárový kód“.</string>
|
||||
<string name="settings_brown_theme">Hnědá</string>
|
||||
<string name="settings_grey_theme">Šedá</string>
|
||||
<string name="settings_green_theme">Zelená</string>
|
||||
@@ -109,11 +108,11 @@
|
||||
<string name="settings_pink_theme">Růžová</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_theme_color">Barva motivu</string>
|
||||
<string name="settings_system_locale">Systém</string>
|
||||
<string name="settings_system_locale">Podle systému</string>
|
||||
<string name="settings_locale">Jazyk</string>
|
||||
<string name="turn_flashlight_off">Vypnout světlo</string>
|
||||
<string name="turn_flashlight_on">Zapnout světlo</string>
|
||||
<string name="failedGeneratingShareURL">Nepodařilo se vygenerovat sdílenou adresu URL. Nahlaste to prosím.</string>
|
||||
<string name="failedGeneratingShareURL">Nepodařilo se vygenerovat adresu URL pro sdílení. Nahlaste to prosím.</string>
|
||||
<string name="passwordRequired">Zadejte prosím heslo</string>
|
||||
<string name="no">Ne</string>
|
||||
<string name="yes">Ano</string>
|
||||
@@ -126,30 +125,30 @@
|
||||
<string name="photos">Fotky</string>
|
||||
<string name="backImageDescription">Obrázek zadní strany</string>
|
||||
<string name="frontImageDescription">Obrázek přední strany</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Chci s Vámi sdílet kartu</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID zkopírováno do schránky</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Chci s vámi sdílet karty</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID zkopírována do schránky</string>
|
||||
<string name="wrongValueForBarcodeType">Hodnota není platná pro vybraný typ čárového kódu</string>
|
||||
<string name="unsupportedBarcodeType">Tento typ čárového kódu zatím nelze zobrazit. Možná bude podporován v pozdější verzi aplikace.</string>
|
||||
<string name="barcodeId">Hodnota čárového kódu</string>
|
||||
<string name="setBarcodeId">Nastavení hodnoty čárového kódu</string>
|
||||
<string name="sameAsCardId">Stejné jako ID</string>
|
||||
<string name="importVoucherVaultMessage">Vyberte svůj <i>vouchervault.json</i> export z Voucher Vault, který chcete importovat.
|
||||
\nVytvořte jej tak, že nejprve stisknete tlačítko Exportovat v aplikaci Voucher Vault.</string>
|
||||
<string name="importVoucherVault">Import z Voucher Vault</string>
|
||||
<string name="importStocardMessage">Vyberte svůj <i>***-sync.zip</i> export z aplikace Stocard, který chcete importovat.
|
||||
\nZískejte ji zasláním e-mailu na adresu support@stocardapp.com s žádostí o export vašich dat.</string>
|
||||
<string name="importVoucherVaultMessage">Vyberte k importu svůj <i>vouchervault.json</i> exportovaný z Voucher Vault.
|
||||
\nVytvoříte jej tak, že nejprve stisknete tlačítko Exportovat v aplikaci Voucher Vault.</string>
|
||||
<string name="importVoucherVault">Import z Voucher Vault</string>
|
||||
<string name="importStocardMessage">Vyberte k importu svůj <i>***-sync.zip</i> exportovaný z aplikace Stocard.
|
||||
\nZískejte ji zasláním e-mailu na adresu support@stocardapp.com s žádostí o export vašich dat.</string>
|
||||
<string name="importStocard">Import ze Stocard</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Vyberte export <i>LoyaltyCardKeychain.csv</i> z klíčenky věrnostních karet, který chcete importovat.
|
||||
\nVytvořte jej z nabídky Import/Export v Loyalty Card Keychain tak, že tam nejprve stisknete tlačítko Exportovat.</string>
|
||||
<string name="importLoyaltyCardKeychain">Import z Loyalty Card Keychain</string>
|
||||
<string name="importFidmeMessage">Vyberte svůj <i>fidme-export-request-xxxxxx.zip</i> export z FidMe k importu a poté vyberte typy čárových kódů ručně.
|
||||
\nVytvořte jej ze svého profilu FidMe tak, že nejprve zvolíte možnost Ochrana dat a poté stisknete tlačítko Extract moje data.</string>
|
||||
<string name="importFidme">Import z FidMe</string>
|
||||
<string name="importCatimaMessage">Vyberte export <i>catima.zip</i> z programu Catima, který chcete importovat.
|
||||
\nVytvořte jej z nabídky Import/Export jiné aplikace Catima tak, že v ní nejprve stisknete tlačítko Exportovat.</string>
|
||||
<string name="importCatima">Import z Catima</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Vyberte k importu <i>LoyaltyCardKeychain.csv</i> exportovaný z Loyalty Card Keychain.
|
||||
\nVytvoříte jej z nabídky Import/Export v Loyalty Card Keychain tak, že tam nejprve stisknete tlačítko Exportovat.</string>
|
||||
<string name="importLoyaltyCardKeychain">Import z Loyalty Card Keychain</string>
|
||||
<string name="importFidmeMessage">Vyberte k importu svůj <i>fidme-export-request-xxxxxx.zip</i> exportovaný z FidMe a poté vyberte typy čárových kódů ručně.
|
||||
\nVytvoříte jej ze svého profilu FidMe tak, že nejprve zvolíte možnost Ochrana dat a poté stisknete tlačítko Extrahovat moje data.</string>
|
||||
<string name="importFidme">Import z FidMe</string>
|
||||
<string name="importCatimaMessage">Vyberte <i>catima.zip</i> exportovaný z aplikace Catima, který chcete importovat.
|
||||
\nVytvoříte jej z nabídky Import/Export jiné aplikace Catima tak, že v ní nejprve stisknete tlačítko Exportovat.</string>
|
||||
<string name="importCatima">Import z Catima</string>
|
||||
<string name="accept">Přijmout</string>
|
||||
<string name="privacy_policy_popup_text">Oznámení o zásadách ochrany osobních údajů (vyžadováno některými obchody s aplikacemi):
|
||||
<string name="privacy_policy_popup_text">Oznámení o zásadách ochrany osobních údajů (vyžadováno některými obchody s aplikacemi):
|
||||
\n
|
||||
\nNejsou shromažďovány žádné údaje, což může potvrdit každý, protože naše aplikace je svobodný software.</string>
|
||||
<string name="privacy_policy">Zásady soukromí</string>
|
||||
@@ -160,9 +159,9 @@
|
||||
<string name="currency">Měna</string>
|
||||
<string name="balance">Zůstatek</string>
|
||||
<string name="errorReadingImage">Obrázek se nepodařilo přečíst</string>
|
||||
<string name="noBarcodeFound">Čarový kód nenalezen</string>
|
||||
<string name="noBarcodeFound">Čárový kód nenalezen</string>
|
||||
<string name="groupsList">Skupiny: <xliff:g>%s</xliff:g></string>
|
||||
<string name="addFromImage">Výběr obrázku z galerie</string>
|
||||
<string name="addFromImage">Výběr obrázku z galerie</string>
|
||||
<string name="addManually">Ruční zadání ID</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Ukončit bez uložení\?</string>
|
||||
<string name="leaveWithoutSaveTitle">Ukončit</string>
|
||||
@@ -194,36 +193,36 @@
|
||||
<string name="sort_by_expiry">Vypršení</string>
|
||||
<string name="sort_by_most_recently_used">Naposledy použité</string>
|
||||
<string name="sort_by_name">Název</string>
|
||||
<string name="swipeToSwitchImages">Přejetím nebo dlouhým stisknutím přepínáte obrázky</string>
|
||||
<string name="swipeToSwitchImages">Přejetím přepínáte obrázky, dlouhým stisknutím otevřete obrázek v aplikaci pro galerii</string>
|
||||
<string name="sort">Seřadit</string>
|
||||
<string name="barcodeImageDescriptionWithType">Obrázek čárového kódu <xliff:g>%s</xliff:g></string>
|
||||
<string name="version_history">Historie verzí</string>
|
||||
<string name="rate_this_app">Ohodnoťte tuto aplikaci</string>
|
||||
<string name="and_data_usage">a využití dat</string>
|
||||
<string name="credits">Kredity</string>
|
||||
<string name="credits">Zásluhy</string>
|
||||
<string name="on_github">na GitHubu</string>
|
||||
<string name="source_repository">Úložiště zdrojů</string>
|
||||
<string name="license">Licence</string>
|
||||
<string name="help_translate_this_app">Pomozte s překladem této aplikace</string>
|
||||
<string name="help_translate_this_app">Pomozte s překladem této aplikace</string>
|
||||
<string name="report_error">Nahlásit chybu</string>
|
||||
<string name="on_google_play">na Google Play</string>
|
||||
<string name="exportPassword">Nastavení hesla pro ochranu exportu (volitelné)</string>
|
||||
<string name="exportPasswordHint">Zadejte heslo</string>
|
||||
<string name="selectColor">Vyberte barvu</string>
|
||||
<string name="selectColor">Vybrat barvu</string>
|
||||
<string name="setIcon">Nastavit ikonu</string>
|
||||
<string name="group_edit">Upravit skupinu</string>
|
||||
<string name="group_name_already_in_use">Již použitý název skupiny</string>
|
||||
<string name="group_name_already_in_use">Název skupiny je již použitý</string>
|
||||
<string name="group_name_is_empty">Název skupiny nemůže být prázdný</string>
|
||||
<string name="group_updated">Skupina aktualizována</string>
|
||||
<string name="editGroup">Úprava skupiny: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noGiftCardsGroup">Zatím nemáte žádné věrnostní karty. Jakmile nějaké přidáte, můžete je přiřadit do skupiny zde.</string>
|
||||
<string name="noGiftCardsGroup">Zatím nemáte žádné věrnostní karty. Jakmile nějaké přidáte, můžete je zde přiřadit do skupiny.</string>
|
||||
<string name="shortcutSelectCard">Vybrat kartu</string>
|
||||
<string name="action_show_details">Zobrazit detaily</string>
|
||||
<string name="action_hide_details">Skrýt detaily</string>
|
||||
<string name="translate_platform">na Weblate</string>
|
||||
<string name="showMoreInfo">Zobrazit podrobnosti</string>
|
||||
<string name="hideMoreInfo">Skrýt podrobnosti</string>
|
||||
<string name="starred">S hvězdičkou</string>
|
||||
<string name="starred">S hvězdičkou</string>
|
||||
<string name="set_scale">Nastavení měřítka</string>
|
||||
<string name="options">Volby</string>
|
||||
<plurals name="balancePoints">
|
||||
@@ -238,11 +237,42 @@
|
||||
<string name="settings_lock_on_opening_orientation">Zamknout podle orientace použité při otevření karty</string>
|
||||
<string name="archive">Archivovat</string>
|
||||
<string name="unarchive">Vrátit z archivu</string>
|
||||
<string name="archiveList">Archivovat</string>
|
||||
<string name="archiveList">Archiv</string>
|
||||
<string name="noUnarchivedCardsMessage">Nejsou žádné karty vrácené z archivu</string>
|
||||
<string name="unarchived">Karta vrácena z archivu</string>
|
||||
<string name="settings_card_orientation">Orientace čárového kódu</string>
|
||||
<string name="settings_landscape_orientation">Na šířku</string>
|
||||
<string name="duplicateCard">Duplikovat</string>
|
||||
<string name="archived">Karta archivována</string>
|
||||
<string name="failedLaunchingPhotoPicker">Nepodařilo se najít podporovanou aplikaci galerie</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> karta (<xliff:g id="archivedCount">%2$d</xliff:g> archivovaná)</item>
|
||||
<item quantity="few"><xliff:g>%1$d</xliff:g> karty (<xliff:g id="archivedCount">%2$d</xliff:g> archivované)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> karet (<xliff:g id="archivedCount">%2$d</xliff:g> archivovaných)</item>
|
||||
</plurals>
|
||||
<string name="previousCard">Předchozí</string>
|
||||
<string name="nextCard">Následující</string>
|
||||
<string name="failedToOpenUrl">Nejprve nainstalujte webový prohlížeč</string>
|
||||
<string name="welcome">Vítejte v Catima</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Zobrazit archiv (<xliff:g>%1$d</xliff:g> karta)</item>
|
||||
<item quantity="few">Zobrazit archiv (<xliff:g>%1$d</xliff:g> karty)</item>
|
||||
<item quantity="other">Zobrazit archiv (<xliff:g>%1$d</xliff:g> karet)</item>
|
||||
</plurals>
|
||||
<string name="barcodeLongPressMessage">V aplikaci pro galerii mohou být otevírány pouze obrázky</string>
|
||||
<string name="failedToRetrieveImageFile">Nepodařilo se získat soubor obrázku</string>
|
||||
<string name="cameraPermissionDeniedTitle">Nelze získat přístup k fotoaparátu</string>
|
||||
<string name="importCards">Importovat karty</string>
|
||||
<string name="updateBalance">Aktualizovat zůstatek</string>
|
||||
<string name="currentBalanceSentence">Současný zůstatek: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Pro skenování čárových kódů bude Catima potřebovat přístup k fotoaparátu. Klepněte zde pro změnu nastavení oprávnění.</string>
|
||||
<string name="updateBalanceTitle">Kolik jste utratil\?</string>
|
||||
<string name="updateBalanceHint">Zadejte výši</string>
|
||||
<string name="newBalanceSentence">Nový zůstatek: <xliff:g>%s</xliff:g></string>
|
||||
<string name="storageReadPermissionRequired">Pro tuto akci je potřeba oprávnění ke čtení úložiště…</string>
|
||||
<string name="cameraPermissionRequired">Pro tuto akci je potřeba oprávnění k přístupu k fotoaparátu…</string>
|
||||
<string name="validFromDate">Platnost od</string>
|
||||
<string name="anyDate">Jakékoliv datum</string>
|
||||
<string name="chooseValidFromDate">Vyberte datum počátku platnosti</string>
|
||||
<string name="validFromSentence">Platnost od: <xliff:g>%s</xliff:g></string>
|
||||
</resources>
|
||||
@@ -67,7 +67,6 @@
|
||||
<string name="importOptionFilesystemExplanation">Vælg en bestemt fil fra filsystemet.</string>
|
||||
<string name="importOptionFilesystemTitle">Import fra filsystem</string>
|
||||
<string name="exportOptionExplanation">Dataene skrives til en placering efter eget valg.</string>
|
||||
<string name="noExternalStoragePermissionError">Giv først tilladelse til ekstern lagring til at importere eller eksportere kort</string>
|
||||
<string name="failedParsingImportUriError">Kunne ikke analysere import-URI\'en</string>
|
||||
<string name="noCardExistsError">Kunne ikke finde kort</string>
|
||||
<string name="noCardIdError">Der er ikke angivet noget kort-ID</string>
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
<string name="exportFailed">Export konnte nicht durchgeführt werden</string>
|
||||
<string name="importing">Importiere…</string>
|
||||
<string name="exporting">Exportiere…</string>
|
||||
<string name="noExternalStoragePermissionError">Berechtigung für den externen Speicher zum Importieren oder Exportieren von Daten erteilen</string>
|
||||
<string name="importOptionFilesystemTitle">Importiere aus dem Dateisystem</string>
|
||||
<string name="importOptionFilesystemExplanation">Wähle eine Datei vom Dateisystem aus.</string>
|
||||
<string name="importOptionFilesystemButton">Wähle vom Dateisystem</string>
|
||||
@@ -53,7 +52,7 @@
|
||||
<string name="thumbnailDescription">Vorschaubild</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="settings_category_title_ui">Benutzeroberfläche</string>
|
||||
<string name="settings_display_barcode_max_brightness">Barcodeansicht aufhellen</string>
|
||||
<string name="settings_display_barcode_max_brightness">Displayhelligkeit in der Barcodeansicht erhöhen</string>
|
||||
<string name="exportSuccessful">Daten exportiert</string>
|
||||
<string name="importSuccessful">Daten importiert</string>
|
||||
<string name="intent_import_card_from_url_share_text">Ich würde gerne diese Karte mit dir teilen</string>
|
||||
@@ -106,7 +105,7 @@
|
||||
<string name="expiryStateSentenceExpired">Abgelaufen: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">Läuft ab: <xliff:g>%s</xliff:g></string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Sperrbildschirm verhindern</string>
|
||||
<string name="settings_keep_screen_on">Bildschirm aktiv halten</string>
|
||||
<string name="settings_keep_screen_on">Bildschirm aktiv lassen</string>
|
||||
<string name="privacy_policy_popup_text">Hinweis zum Datenschutz (oft gefordert):
|
||||
\n
|
||||
\nKEINE DATEN WERDEN GESAMMELT, was jeder bestätigen kann, da unsere Anwendung eine freie Software ist.</string>
|
||||
@@ -185,7 +184,7 @@
|
||||
<string name="settings_theme_color">Designfarbe</string>
|
||||
<string name="app_contributors">Ermöglicht durch: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="barcodeImageDescriptionWithType">Bild <xliff:g>%s</xliff:g> Barcode</string>
|
||||
<string name="swipeToSwitchImages">Wischen oder langes Drücken zum Wechseln der Bilder</string>
|
||||
<string name="swipeToSwitchImages">Wischen zum Wechseln der Bilder, Halten zum Öffnen des Bildes in der Galerie</string>
|
||||
<string name="sort_by">Sortieren nach</string>
|
||||
<string name="sort_by_balance">Kontostand</string>
|
||||
<string name="sort_by_expiry">Ablaufdatum</string>
|
||||
@@ -226,7 +225,7 @@
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> Punkt</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> Punkte</item>
|
||||
</plurals>
|
||||
<string name="settings_oled_dark">Rein schwarzer Hintergrund für dunkles Thema</string>
|
||||
<string name="settings_oled_dark">Komplett schwarzer Hintergrund im dunklen Design</string>
|
||||
<string name="include_if_asking_support">Wenn Sie Unterstützung anfordern möchten, geben Sie bitte die folgenden Informationen an:</string>
|
||||
<string name="settings_follow_system_orientation">System folgen</string>
|
||||
<string name="settings_landscape_orientation">Landschaft</string>
|
||||
@@ -240,4 +239,33 @@
|
||||
<string name="archive">Archivieren</string>
|
||||
<string name="archived">Karte archiviert</string>
|
||||
<string name="settings_lock_on_opening_orientation">Kartenausrichtung nach dem Öffnen beibehalten</string>
|
||||
</resources>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> Karte (<xliff:g id="archivedCount">%2$d</xliff:g> archiviert)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> Karten (<xliff:g id="archivedCount">%2$d</xliff:g> archiviert)</item>
|
||||
</plurals>
|
||||
<string name="failedLaunchingPhotoPicker">Es konnte keine unterstützte Galerie-Anwendung gefunden werden</string>
|
||||
<string name="previousCard">Vorherige</string>
|
||||
<string name="nextCard">Nächste</string>
|
||||
<string name="failedToOpenUrl">Installieren Sie zunächst einen Webbrowser</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Archiv ansehen (<xliff:g>%1$d</xliff:g> Karte)</item>
|
||||
<item quantity="other">Archiv ansehen (<xliff:g>%1$d</xliff:g> Karten)</item>
|
||||
</plurals>
|
||||
<string name="welcome">Willkommen bei Catima</string>
|
||||
<string name="barcodeLongPressMessage">In der Galerie können nur Bilder geöffnet werden</string>
|
||||
<string name="failedToRetrieveImageFile">Bilddatei konnte nicht abgerufen werden</string>
|
||||
<string name="updateBalanceTitle">Wie viel haben Sie ausgegeben\?</string>
|
||||
<string name="cameraPermissionDeniedTitle">Kein Zugriff auf die Kamera möglich</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Um Strichcodes zu scannen, benötigt Catima Zugriff auf Ihre Kamera. Tippen Sie hier, um Ihre Berechtigungseinstellungen zu ändern.</string>
|
||||
<string name="updateBalanceHint">Betrag eingeben</string>
|
||||
<string name="importCards">Karten importieren</string>
|
||||
<string name="currentBalanceSentence">Aktuelles Guthaben: <xliff:g>%s</xliff:g></string>
|
||||
<string name="newBalanceSentence">Neues Guthaben: <xliff:g>%s</xliff:g></string>
|
||||
<string name="updateBalance">Guthaben aktualisieren</string>
|
||||
<string name="storageReadPermissionRequired">Berechtigung zum Lesen des Speichers für diese Aktion erforderlich …</string>
|
||||
<string name="cameraPermissionRequired">Für diese Aktion wird die Erlaubnis zum Zugriff auf die Kamera benötigt …</string>
|
||||
<string name="validFromDate">Gültig ab</string>
|
||||
<string name="validFromSentence">Gültig ab: <xliff:g>%s</xliff:g></string>
|
||||
<string name="chooseValidFromDate">Gültig-ab-Datum wählen</string>
|
||||
<string name="anyDate">Beliebiges Datum</string>
|
||||
</resources>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="action_add">Προσθήκη</string>
|
||||
<string name="noGiftCards">Δεν έχετε κάρτες προς το παρόν. Πατήστε το κουμπί \"+\" (συν) στο πάνω μέρος για να ξεκινήσετε.\n\nΤο Loyalty Card Keychain σας δίνει τη δυνατότητα να έχετε τις κάρτες σας στο τηλέφωνο σας, έτσι ώστε να τις έχετε πάντα μαζί σας.</string>
|
||||
<string name="storeName">Κατάστημα</string>
|
||||
<string name="noGiftCards">Κάντε κλικ στο + κουμπί για να προσθέσετε μία κάρτα ή προσθέστε από το ⋮ μενού.</string>
|
||||
<string name="storeName">Όνομα</string>
|
||||
<string name="note">Σημείωση</string>
|
||||
<string name="cardId">Κωδικός Κάρτας</string>
|
||||
<string name="cancel">Άκυρο</string>
|
||||
@@ -15,46 +15,45 @@
|
||||
<string name="sendLabel">Αποστολή…</string>
|
||||
<string name="editCardTitle">Επεξεργασία Κάρτας</string>
|
||||
<string name="addCardTitle">Προσθήκη Κάρτας</string>
|
||||
<string name="scanCardBarcode">Σαρώστε τον κωδικό της κάρτας</string>
|
||||
<string name="scanCardBarcode">Σαρώστε τον γραμμοκώδικα (bardcode)</string>
|
||||
<string name="cardShortcut">Συντόμευση Κάρτας</string>
|
||||
<string name="noCardsMessage">Δεν υπάρχουν κάρτες. προσθέστε μία πρώτα</string>
|
||||
<string name="noStoreError">Δεν δώσατε κατάστημα</string>
|
||||
<string name="noCardIdError">Δεν δώσατε κωδικό κάρτας</string>
|
||||
<string name="noCardExistsError">Δεν ήταν δυνατό να εντοπιστεί κάρτα</string>
|
||||
<string name="noCardsMessage">Προσθέστε μία κάρτα πρώτα</string>
|
||||
<string name="noStoreError">Δεν έχει εισαχθεί όνομα</string>
|
||||
<string name="noCardIdError">Δεν έχει εισαχθεί κωδικός</string>
|
||||
<string name="noCardExistsError">Δεν ήταν δυνατό να εντοπιστεί η κάρτα</string>
|
||||
<string name="importExport">Εισαγωγή/Εξαγωγή</string>
|
||||
<string name="exportName">Εξαγωγή</string>
|
||||
<string name="importExportHelp">Τα εφεδρικά δεδομένα σας δίνουν την δυνατότητα να μεταφέρετε τις κάρτες σας σε μία άλλη συσκευή.</string>
|
||||
<string name="importSuccessfulTitle">Εισαγωγή επιτυχής</string>
|
||||
<string name="importExportHelp">Τα αντίγραφα ασφαλείας, σας επιτρέπουν να τα εισάγετε σε άλλη συσκευή.</string>
|
||||
<string name="importSuccessfulTitle">Εισήχθησαν</string>
|
||||
<string name="importFailedTitle">Εισαγωγή ανεπιτυχής</string>
|
||||
<string name="importFailed">Δεν εισήχθει</string>
|
||||
<string name="importFailed">Δεν ήταν δυνατή η εισαγωγή</string>
|
||||
<string name="exportSuccessfulTitle">Εξαγωγή επιτυχής</string>
|
||||
<string name="exportFailedTitle">Εξαγωγή ανεπιτυχής</string>
|
||||
<string name="exportFailed">Δεν εξήχθη</string>
|
||||
<string name="exportFailed">Δεν ήταν δυνατή η εξαγωγή</string>
|
||||
<string name="importing">Γίνεται εισαγωγή του…</string>
|
||||
<string name="exporting">Γίνεται εξαγωγή του…</string>
|
||||
<string name="noExternalStoragePermissionError">Δεν είναι δυνατή η εισαγωγή ή εξαγωγή καρτών χωρίς την άδεια πρόσβασης στον εξωτερικό χώρο αποθήκευσης</string>
|
||||
<string name="importOptionFilesystemTitle">Εισαγωγή από το σύστημα αρχείων</string>
|
||||
<string name="importOptionFilesystemExplanation">Επιλέξτε ένα συγκεκριμένο αρχείο από το σύστημα αρχείων.</string>
|
||||
<string name="importOptionFilesystemButton">Από το σύστημα αρχείων</string>
|
||||
<string name="importOptionApplicationTitle">Χρήση εξωτερικής εφαρμογής</string>
|
||||
<string name="importOptionApplicationExplanation">Κάντε χρήση μίας εξωτερικής εφαρμογής όπως είναι τα Dropbox, Google Drive ή ο αγαπημένος σας διαχειριστής αρχείων για να ανοίξετε ένα αρχείο.</string>
|
||||
<string name="importOptionApplicationButton">Χρήση εξωτερικής εφαρμογής</string>
|
||||
<string name="importOptionApplicationTitle">Χρήση άλλης εφαρμογής</string>
|
||||
<string name="importOptionApplicationExplanation">Χρησιμοποιήστε οποιαδήποτε εφαρμογή ή τον αγαπημένο περιηγητή αρχείων σας, για να ανοίξετε ένα αρχείο.</string>
|
||||
<string name="importOptionApplicationButton">Χρήσης άλλης εφαρμογής</string>
|
||||
<string name="about">Σχετικά</string>
|
||||
<string name="app_license">Άδεια χρήσης υπό το GPLv3.</string>
|
||||
<string name="app_license">Άδεια χρήσης υπό GPLv3+</string>
|
||||
<string name="about_title_fmt">Σχετικά με <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Έκδοση: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Πληροφορίες Αναθεώρησης: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="selectBarcodeTitle">Επιλέξτε Barcode</string>
|
||||
<string name="copy_to_clipboard_toast">Ο κωδικός της κάρτας αντιγράφτηκε στο πρόχειρο</string>
|
||||
<string name="thumbnailDescription">Μικρογραφία κάρτας</string>
|
||||
<string name="copy_to_clipboard_toast">Ο κωδικός αντιγράφτηκε στο πρόχειρο</string>
|
||||
<string name="thumbnailDescription">Μικρογραφία</string>
|
||||
<string name="settings">Ρυθμίσεις</string>
|
||||
<string name="settings_category_title_ui">Διεπαφή χρήστη</string>
|
||||
<string name="settings_dark_theme">Σκοτεινό</string>
|
||||
<string name="settings_light_theme">Φωτεινό</string>
|
||||
<string name="settings_system_theme">Σύστημα</string>
|
||||
<string name="barcode">Γραμμικός κώδικας</string>
|
||||
<string name="deleteTitle">Αφαίρεση Κάρτας</string>
|
||||
<string name="deleteConfirmation">Παρακαλώ επιβεβαιώστε ότι θέλετε να διαγράψετε αυτή την κάρτα.</string>
|
||||
<string name="deleteTitle">Διαγραφή Κάρτας</string>
|
||||
<string name="deleteConfirmation">Μόνιμη διαγραφή της κάρτας;</string>
|
||||
<string name="action_search">Αναζήτηση</string>
|
||||
<string name="noMatchingGiftCards">Κανένα αποτέλεσμα. Δοκίμασε με διαφορετικές λέξεις.</string>
|
||||
<plurals name="selectedCardCount">
|
||||
@@ -62,4 +61,205 @@
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> επιλέγχθηκαν</item>
|
||||
</plurals>
|
||||
<string name="noGiftCardsGroup">Δημιούργησε κάρτες και βάλτες σε αυτή την ομάδα.</string>
|
||||
<string name="barcodeNoBarcode">Δεν υπάρχει barcode</string>
|
||||
<string name="addManually">Χειροκίνητη εισαγωγή κωδικού</string>
|
||||
<string name="never">Ποτέ</string>
|
||||
<string name="share">Κοινοποίηση</string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> πόντος</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> πόντοι</item>
|
||||
</plurals>
|
||||
<string name="exportOptionExplanation">Τα δεδομένα θα μεταφερθούν σε τοποθεσία της επιλογής σας.</string>
|
||||
<string name="settings_theme">Θέμα</string>
|
||||
<string name="groupsList">Ομάδες: <xliff:g>%s</xliff:g></string>
|
||||
<string name="barcodeId">Τιμή γραμμοκώδικα</string>
|
||||
<string name="sort">Ταξινόμηση</string>
|
||||
<string name="deleteConfirmationGroup">Διαγραφή ομάδας;</string>
|
||||
<string name="moveDown">Προχώρα κάτω</string>
|
||||
<string name="accept">Αποδοχή</string>
|
||||
<string name="yes">Ναι</string>
|
||||
<string name="no">Όχι</string>
|
||||
<string name="addFromImage">Επιλογή εικόνας από την συλλογή</string>
|
||||
<string name="expiryStateSentence">Λήγει: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryDate">Ημερομηνία λήξης</string>
|
||||
<string name="settings_keep_screen_on">Κράτα την οθόνη ανοιχτή</string>
|
||||
<string name="leaveWithoutSaveTitle">Έξοδος</string>
|
||||
<string name="swipeToSwitchImages">Σύρετε για να αλλάξετε εικόνες, κρατήστε για να ανοίξετε μια εικόνα στην συλλογή</string>
|
||||
<string name="sort_by_balance">Υπόλοιπο</string>
|
||||
<string name="reverse">... σε αντίθετη σειρά</string>
|
||||
<string name="version_history">Ιστορικό έκδοσης</string>
|
||||
<string name="sort_by">Ταξινόμηση κατά</string>
|
||||
<string name="credits">Πιστώσεις</string>
|
||||
<string name="help_translate_this_app">Βοηθήστε να μεταφραστεί η εφαρμογή</string>
|
||||
<string name="source_repository">Αποθήκη κώδικα</string>
|
||||
<string name="on_github">στο GitHub</string>
|
||||
<string name="on_google_play">στο Google Play</string>
|
||||
<string name="report_error">Αναφορά Σφάλματος</string>
|
||||
<string name="starred">Αγαπημένα</string>
|
||||
<string name="translate_platform">στο Weblate</string>
|
||||
<string name="set_scale">Ορίστε κλίμακα</string>
|
||||
<string name="importLoyaltyCardKeychain">Εισαγωγή από Loyalty Card Keychain</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Επιλέξτε την <i>LoyaltyCardKeychain.csv</i> εξαγωγή από το Loyalty Card Keychain για εισαγωγή.
|
||||
\nΔημιουργήστε το από το μενού Εισαγωγής/Εξαγωγής στο Loyalty Card Keychain επιλέγοντας Εξαγωγή.</string>
|
||||
<string name="importFidme">Εισαγωγή από FidMe</string>
|
||||
<string name="importFidmeMessage">Επιλέξτε την <i>fidme-export-request-xxxxxx.zip</i> εξαγωγή από το FidMe για εισαγωγή και επιλέξτε χειροκίνητα τους τύπους γραμμοκώδικα μετέπειτα.
|
||||
\nΔημιουργήστε το από το FidMe προφίλ επιλέγοντας Προστασία Δεδομένων και διαλέγοντας εξαγωγή δεδομένων.</string>
|
||||
<string name="setBarcodeId">Επιλέξτε τιμή γραμμοκώδικα</string>
|
||||
<string name="wrongValueForBarcodeType">Η τιμή δεν είναι έγκυρη για αυτού του τύπου γραμμοκώδικα</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">Οι κωδικοί αντιγράφηκαν στο πρόχειρο</string>
|
||||
<string name="setBackImage">Επιλογή οπίσθιας εικόνας</string>
|
||||
<string name="removeImage">Αφαίρεση εικόνας</string>
|
||||
<string name="takePhoto">Τραβήξτε μια φωτογραφία</string>
|
||||
<string name="updateBarcodeQuestionText">Αλλάξατε τον κωδικό. Θέλετε να ενημερώσετε και τον γραμμοκώδικα στην ίδια τιμή;</string>
|
||||
<string name="action_show_details">Εμφάνιση λεπτομερειών</string>
|
||||
<string name="options">Επιλογές</string>
|
||||
<string name="hideMoreInfo">Απόκρυψη πληροφοριών</string>
|
||||
<string name="noGroupCards">Αυτή η ομάδα είναι άδεια</string>
|
||||
<string name="settings_display_barcode_max_brightness">Επιπλέον φωτισμός γραμμοκώδικα</string>
|
||||
<string name="group_name_is_empty">Το όνομα ομάδας δεν γίνεται να είναι κενό</string>
|
||||
<string name="group_edit">Επεξεργασία ομάδας</string>
|
||||
<string name="star">Προσθήκη στα αγαπημένα</string>
|
||||
<string name="unstar">Αφαίρεση από τα αγαπημένα</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Διαγραφή <xliff:g>%d</xliff:g> κάρτας</item>
|
||||
<item quantity="other">Διαγραφή <xliff:g>%d</xliff:g> καρτών</item>
|
||||
</plurals>
|
||||
<string name="card_ids_copied">Αντιγραμμένη/ες ταυτότητα/ες</string>
|
||||
<string name="errorReadingImage">Δεν ήταν δυνατό να διαβαστεί η εικόνα</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> δεν φαίνεται να είναι έγκυρο το υπόλοιπο.</string>
|
||||
<string name="currency">Νόμισμα</string>
|
||||
<string name="privacy_policy">Πολιτική απορρήτου</string>
|
||||
<string name="chooseImportType">Εισαγωγή δεδομένων από</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="privacy_policy_popup_text">Σημείωμα πολιτικής απορρήτου ( υποχρεωτικό σε κάποια \"μαγαζιά\" εφαρμογών)
|
||||
\n
|
||||
\nΜΗΔΕΝΙΚΆ ΔΕΔΟΜΈΝΑ ΣΥΛΛΈΓΟΝΤΑΙ, ο οποιοσδήποτε μπορεί να το επιβεβαιώσει μιας και η εφαρμογή είναι ελεύθερο λογισμικό.</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> κάρτα ( <xliff:g id="archivedCount">%2$d</xliff:g> αρχειοθετήθηκε)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> κάρτες ( <xliff:g id="archivedCount">%2$d</xliff:g> αρχειοθετήθηκαν)</item>
|
||||
</plurals>
|
||||
<string name="importCatimaMessage">Επιλέξτε την <i>catima.zip</i> εξαγωγή από το Catima για εισαγωγή
|
||||
\nΔημιουργήστε το από το μενού Εισαγωγής/Εξαγωγής μιας άλλης εφαρμογής Catima κάνοντας εξαγωγή εκεί πρώτα.</string>
|
||||
<string name="importStocardMessage">Επιλέξτε την <i>***-sync.zip</i> εξαγωγή από το Stocard για εισαγωγή.
|
||||
\nΠάρτε το στέλνοντας email στο: support@stocardapp.com ζητώντας μια εξαγωγή αρχείων των δεδομένων σας.</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Θέλω να μοιραστώ μερικές κάρτες μαζί σου</string>
|
||||
<string name="editGroup">Επεξεργασία Ομάδας: <xliff:g>%s</xliff:g></string>
|
||||
<string name="setFrontImage">Επιλογή μπροστινής εικόνας</string>
|
||||
<string name="importVoucherVaultMessage">Επιλέξτε την <i>vouchervault.json</i> εξαγωγή από το Voucher Vault για εισαγωγή.
|
||||
\nΔημιουργήστε το επιλέγοντας Εξαγωγή στο Voucher Vault.</string>
|
||||
<string name="unsupportedBarcodeType">Ο τύπος γραμμοκώδικα δεν γίνεται να εμφανιστεί ακόμα. Μπορεί να υποστηρίζεται σε μια μελλοντική έκδοση της εφαρμογής.</string>
|
||||
<string name="frontImageDescription">Μπροστινή εικόνα</string>
|
||||
<string name="photos">Φωτογραφίες</string>
|
||||
<string name="backImageDescription">Οπίσθια εικόνα</string>
|
||||
<string name="updateBarcodeQuestionTitle">Ενημέρωση τιμής γραμμοκώδικα;</string>
|
||||
<string name="passwordRequired">Παρακαλώ εισάγετε τον κωδικό</string>
|
||||
<string name="sort_by_most_recently_used">Χρησιμοποιήθηκαν πρόσφατα</string>
|
||||
<string name="shortcutSelectCard">Επιλέξτε μία κάρτα</string>
|
||||
<string name="barcodeImageDescriptionWithType">Εικόνα <xliff:g>%s</xliff:g> γραμμοκώδικα</string>
|
||||
<string name="app_libraries">Ελεύθερες βιβλιοθήκες τρίτων: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="license">Άδεια</string>
|
||||
<string name="include_if_asking_support">Αν θέλετε να ζητήσετε υποστήριξη, συμπεριλάβετε τις ακόλουθες πληροφορίες:</string>
|
||||
<string name="action_hide_details">Απόκρυψη λεπτομερειών</string>
|
||||
<string name="importSuccessful">Δεδομένα εισήχθησαν</string>
|
||||
<string name="moveUp">Προχώρα πάνω</string>
|
||||
<string name="barcodeType">Τύπος γραμμοκώδικα</string>
|
||||
<string name="app_resources">Ελεύθερες πηγές τρίτων: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="selectColor">Επιλογή χρώματος</string>
|
||||
<string name="setIcon">Ορισμός εικονιδίου</string>
|
||||
<string name="settings_sky_blue_theme">Γαλάζιο</string>
|
||||
<string name="settings_green_theme">Πράσινο</string>
|
||||
<string name="settings_grey_theme">Γκρι</string>
|
||||
<string name="settings_brown_theme">Καφέ</string>
|
||||
<string name="sort_by_expiry">Λήξη</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> κάρτα</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> κάρτες</item>
|
||||
</plurals>
|
||||
<string name="points">Πόντοι</string>
|
||||
<string name="exportSuccessful">Δεδομένα εξήχθησαν</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Αποτροπή κλειδώματος οθόνης</string>
|
||||
<string name="failedLaunchingPhotoPicker">Δεν βρέθηκε υποστηριζόμενη εφαρμογή συλλογής</string>
|
||||
<string name="noBarcode">Χωρίς barcode</string>
|
||||
<string name="starImage">Αγαπημένο αστέρι</string>
|
||||
<string name="balanceSentence">Υπόλοιπο: <xliff:g>%s</xliff:g></string>
|
||||
<string name="failedParsingImportUriError">Δεν ήταν δυνατή η ανάλυση του εισαγόμενου URL</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Διαγραφή της κάρτας <xliff:g>%d</xliff:g> μόνιμα;</item>
|
||||
<item quantity="other">Διαγραφή των καρτρών <xliff:g>%d</xliff:g> μόνιμα;</item>
|
||||
</plurals>
|
||||
<string name="app_copyright_old">Βασισμένο στο Loyalty Card Keychain
|
||||
\nπνευματικά δικαιώματα © 2016-2020 Branden Archer</string>
|
||||
<string name="enterBarcodeInstructions">Εισάγετε τον κωδικό και διαλέξτε έναν είδος γραμμοκώδικα από κάτω ή \"Δεν υπάρχει γραμμοκώδικας\".</string>
|
||||
<string name="settings_follow_system_orientation">Ακολούθηση συστήματος</string>
|
||||
<string name="settings_card_orientation">Προσανατολισμός γραμμοκώδικα</string>
|
||||
<string name="settings_portrait_orientation">Πορτραίτο</string>
|
||||
<string name="settings_landscape_orientation">Οριζόντια</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Πνευματικά δικαιώματα © 2019-<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="settings_lock_on_opening_orientation">Κλείδωμα τωρινού προσανατολισμού όταν ανοίγει μία κάρτα</string>
|
||||
<string name="settings_max_font_size_scale">Μέγιστο μέγεθος γραμματοσειράς</string>
|
||||
<string name="intent_import_card_from_url_share_text">Θέλω να μοιραστώ μία κάρτα μαζί σου</string>
|
||||
<string name="enter_group_name">Εισάγετε όνομα ομάδας</string>
|
||||
<string name="groups">Ομάδες</string>
|
||||
<string name="noGroups">Κάντε κλικ στο + κουμπί ώστε να προσθέσετε ομάδες για κατηγοριοποίηση.</string>
|
||||
<string name="group_name_already_in_use">Αυτό το όνομα υπάρχει ήδη</string>
|
||||
<string name="group_updated">Η ομάδα ενημερώθηκε</string>
|
||||
<string name="all">Όλες</string>
|
||||
<string name="failedOpeningFileManager">Εγκαταστήστε έναν διαχειριστή αρχείων πρώτα.</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Έξοδος χωρίς αποθήκευση;</string>
|
||||
<string name="expiryStateSentenceExpired">Έληξε: <xliff:g>%s</xliff:g></string>
|
||||
<string name="card">Κάρτα</string>
|
||||
<string name="editBarcode">Επεξεργασία γραμμοκώδικα</string>
|
||||
<string name="chooseExpiryDate">Επιλέξτε ημερομηνία λήξης</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Μετακίνηση του γραμμοκώδικα στο πάνω μέρος της οθόνης</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Κεντράρισμα του γραμμοκώδικα στην οθόνη</string>
|
||||
<string name="noBarcodeFound">Δεν βρέθηκε γραμμοκώδικας</string>
|
||||
<string name="balance">Υπόλοιπο</string>
|
||||
<string name="importCatima">Εισαγωγή από Catima</string>
|
||||
<string name="importStocard">Εισαγωγή από Stocard</string>
|
||||
<string name="importVoucherVault">Εισαγωγή από Voucher Vault</string>
|
||||
<string name="sameAsCardId">Ίδιος κωδικός</string>
|
||||
<string name="exportPassword">Προσθέστε έναν κωδικό για προστασία της εξαγωγής (προαιρετικά)</string>
|
||||
<string name="exportPasswordHint">Εισαγωγή κωδικού</string>
|
||||
<string name="failedGeneratingShareURL">Δεν ήταν δυνατή η δημιουργία κοινοποιούμενου URL. Παρακαλώ αναφέρετε το.</string>
|
||||
<string name="turn_flashlight_on">Ενεργοποίηση φακού</string>
|
||||
<string name="turn_flashlight_off">Απενεργοποίηση φακού</string>
|
||||
<string name="settings_locale">Γλώσσα</string>
|
||||
<string name="settings_oled_dark">Απόλυτο μαύρο φόντο για το μαύρο θέμα</string>
|
||||
<string name="settings_system_locale">Σύστημα</string>
|
||||
<string name="settings_theme_color">Χρώμα θέματος</string>
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_pink_theme">Ροζ</string>
|
||||
<string name="settings_magenta_theme">Φούξια</string>
|
||||
<string name="settings_violet_theme">Βιολετί</string>
|
||||
<string name="settings_blue_theme">Μπλε</string>
|
||||
<string name="app_contributors">Δημιουργήθηκε από: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="showMoreInfo">Εμφάνιση πληροφοριών</string>
|
||||
<string name="sort_by_name">Όνομα</string>
|
||||
<string name="and_data_usage">και δεδομένα χρήσης</string>
|
||||
<string name="rate_this_app">Βαθμολογήστε την εφαρμογή</string>
|
||||
<string name="duplicateCard">Αντίγραφο</string>
|
||||
<string name="archive">Αρχειοθετήστε</string>
|
||||
<string name="archived">Η κάρτα αρχειοθετήθηκε</string>
|
||||
<string name="unarchived">Η κάρτα αφαιρέθηκε από το αρχείο</string>
|
||||
<string name="unarchive">Αφαίρεση από το αρχείο</string>
|
||||
<string name="archiveList">Αρχείο</string>
|
||||
<string name="noUnarchivedCardsMessage">Δεν υπάρχουν αρχειοθετημένες κάρτες</string>
|
||||
<string name="updateBalanceTitle">Πόσα ξοδέψατε;</string>
|
||||
<string name="cameraPermissionDeniedTitle">Αδύνατη η πρόσβαση στην κάμερα</string>
|
||||
<string name="failedToRetrieveImageFile">Αποτυχία ανάκτησης αρχείου εικόνας</string>
|
||||
<string name="previousCard">Προηγούμενη</string>
|
||||
<string name="nextCard">Επόμενη</string>
|
||||
<string name="updateBalance">Ενημέρωση υπολοίπου</string>
|
||||
<string name="barcodeLongPressMessage">Μόνο εικόνες μπορούν να ανοιχτούν στην εφαρμογή φωτογραφιών</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Για να σκανάρετε γραμμοκώδικες, θα χρειαστεί πρόσβαση στην κάμερα από το Catima. Πατήστε εδώ για να δώσετε πρόσβαση.</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Προβολή αρχείου (<xliff:g>%1$d</xliff:g> κάρτας)</item>
|
||||
<item quantity="other">Προβολή αρχείου (<xliff:g>%1$d</xliff:g> καρτών)</item>
|
||||
</plurals>
|
||||
<string name="importCards">Εισαγωγή καρτών</string>
|
||||
<string name="updateBalanceHint">Εισάγετε ποσό</string>
|
||||
<string name="currentBalanceSentence">Τωρινό υπόλοιπο <xliff:g>%s</xliff:g></string>
|
||||
<string name="newBalanceSentence">Νέο υπόλοιπο: <xliff:g>%s</xliff:g></string>
|
||||
<string name="failedToOpenUrl">Εγκαταστήστε έναν περιηγητή πρώτα</string>
|
||||
<string name="welcome">Καλώς ήρθατε στο Catima</string>
|
||||
</resources>
|
||||
2
app/src/main/res/values-enm/strings.xml
Normal file
2
app/src/main/res/values-enm/strings.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -63,7 +63,6 @@
|
||||
<string name="importOptionApplicationTitle">Uzi alian app</string>
|
||||
<string name="importOptionFilesystemExplanation">Elektu specifa dosiero de la dosiersistemo.</string>
|
||||
<string name="exportOptionExplanation">La datumoj estos skribita al loko de via elekto.</string>
|
||||
<string name="noExternalStoragePermissionError">Grant ekstera stokado permeso de importado aŭ eksportado kartoj unua</string>
|
||||
<string name="exportFailed">Ne povis eksporti kartoj</string>
|
||||
<string name="importFailed">Ne povis importi kartoj</string>
|
||||
<string name="importExportHelp">Subtenanta supre vian kartoj permesas vin movi ilin al alia aparato.</string>
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="barcode">Código de barras</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="barcodeNoBarcode">No hay código de barra</string>
|
||||
<string name="storeName">Nombre</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="action_search">Buscar</string>
|
||||
<string name="action_add">Agregar</string>
|
||||
<string name="importFailedTitle">Error al importar</string>
|
||||
<string name="deleteConfirmation">¿Desea eliminar la tarjeta permanentemente\?</string>
|
||||
<string name="exportSuccessfulTitle">Exportado</string>
|
||||
<string name="exportFailedTitle">Error en la exportación</string>
|
||||
<string name="exportFailed">No se pudo exportar</string>
|
||||
<string name="noBarcode">Sin código de barra</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="noGiftCards">Pulsa el botón + para agregar una tarjeta de regalo, o importa desde el menú.</string>
|
||||
<string name="noGiftCardsGroup">Crea tarjetas de regalo, y asignales un grupo.</string>
|
||||
<string name="note">Nota</string>
|
||||
<string name="unstar">Borrar de favoritos</string>
|
||||
<string name="importExport">Importar/Exportar</string>
|
||||
<string name="exportName">Exportar</string>
|
||||
<string name="importExportHelp">Crear una copia de seguridad de sus datos, permite moverlos hacia otro dispositivo.</string>
|
||||
<string name="importing">Importando…</string>
|
||||
<string name="exporting">Exportando…</string>
|
||||
<string name="save">Guardar</string>
|
||||
<string name="failedParsingImportUriError">No se pudo procesar la URI importada</string>
|
||||
<string name="copy_to_clipboard">Copiar ID al portapapeles</string>
|
||||
<string name="barcodeType">Tipo de código de barra</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="sendLabel">Enviando…</string>
|
||||
<string name="noCardsMessage">Agregar tarjeta al principio</string>
|
||||
<string name="noMatchingGiftCards">Sin resultados. Intente cambiando su búsqueda.</string>
|
||||
<string name="noCardExistsError">No se ha podido encontrar la tarjeta</string>
|
||||
<string name="cardId">ID Tarjeta</string>
|
||||
<string name="star">Agregar a favoritos</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="deleteTitle">Eliminar tarjeta</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="addCardTitle">Agregar tarjeta</string>
|
||||
<string name="scanCardBarcode">Escanear código de barra</string>
|
||||
<string name="cardShortcut">Acceso rápido de tarjeta</string>
|
||||
<string name="editCardTitle">Editar tarjeta</string>
|
||||
<string name="card_ids_copied">ID(s) Copiado(s)</string>
|
||||
<string name="importSuccessfulTitle">Importado</string>
|
||||
<string name="importFailed">No se pudo importar</string>
|
||||
</resources>
|
||||
@@ -1,38 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="action_add">Añadir</string>
|
||||
<string name="noGiftCards">Pulse el botón «+» para añadir una tarjeta, o importe algunas del menú ⋮.</string>
|
||||
<string name="noGiftCards">Haz clic en el botón + para añadir una tarjeta, o importa desde el menú ⋮.</string>
|
||||
<string name="storeName">Nombre</string>
|
||||
<string name="note">Nota</string>
|
||||
<string name="cardId">Id. de tarjeta</string>
|
||||
<string name="cardId">ID. de tarjeta</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="save">Guardar</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="confirm">Confirmar</string>
|
||||
<string name="ok">Aceptar</string>
|
||||
<string name="copy_to_clipboard">Copiar id. en portapapeles</string>
|
||||
<string name="copy_to_clipboard">Copiar ID. en portapapeles</string>
|
||||
<string name="sendLabel">Enviar…</string>
|
||||
<string name="editCardTitle">Editar tarjeta</string>
|
||||
<string name="addCardTitle">Añadir tarjeta</string>
|
||||
<string name="scanCardBarcode">Escanear código de barras de la tarjeta</string>
|
||||
<string name="scanCardBarcode">Escanear código de barras</string>
|
||||
<string name="cardShortcut">Atajo de tarjeta</string>
|
||||
<string name="noCardsMessage">Añada una tarjeta primero</string>
|
||||
<string name="noStoreError">No se proporcionó ningún nombre</string>
|
||||
<string name="noCardIdError">Id. de tarjeta no especificado</string>
|
||||
<string name="noCardExistsError">No se ha podido encontrar la tarjeta</string>
|
||||
<string name="importExport">Importar/exportar</string>
|
||||
<string name="noCardIdError">No se ha introducido ninguna código</string>
|
||||
<string name="noCardExistsError">No se ha podido encontrar esa tarjeta</string>
|
||||
<string name="importExport">Importar/Exportar</string>
|
||||
<string name="exportName">Exportar</string>
|
||||
<string name="importExportHelp">El respaldo le permite transferir sus tarjetas a otro dispositivo.</string>
|
||||
<string name="importExportHelp">Hacer una copia de seguridad de los datos permite trasladarlos a otro dispositivo.</string>
|
||||
<string name="importSuccessfulTitle">Importado</string>
|
||||
<string name="importFailedTitle">Falló la importación</string>
|
||||
<string name="importFailed">No se han podido importar tarjetas</string>
|
||||
<string name="importFailed">No se ha podido realizar la importación</string>
|
||||
<string name="exportSuccessfulTitle">Exportado</string>
|
||||
<string name="exportFailedTitle">Falló la exportación</string>
|
||||
<string name="exportFailed">No se han podido exportar las tarjetas</string>
|
||||
<string name="exportFailed">No se han podido exportar</string>
|
||||
<string name="importing">Importando…</string>
|
||||
<string name="exporting">Exportando…</string>
|
||||
<string name="noExternalStoragePermissionError">Otorgar permiso de almacenamiento para importar o exportar tarjetas</string>
|
||||
<string name="importOptionFilesystemTitle">Importar desde el sistema de archivos</string>
|
||||
<string name="importOptionFilesystemExplanation">Elegir un archivo concreto del sistema de archivos.</string>
|
||||
<string name="importOptionFilesystemButton">Desde el sistema de archivos</string>
|
||||
@@ -40,41 +39,41 @@
|
||||
<string name="importOptionApplicationExplanation">Use una aplicación o su gestor de archivos favoritos para abrir un archivo.</string>
|
||||
<string name="importOptionApplicationButton">Utilizar otra aplicación</string>
|
||||
<string name="about">Acerca de</string>
|
||||
<string name="app_license">Programa libre con «copyleft», disponible en virtud de la licencia GPLv3+.</string>
|
||||
<string name="app_license">Programa libre con «copyleft», disponible en virtud de la licencia GPLv3+</string>
|
||||
<string name="about_title_fmt">Acerca de <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versión: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="settings">Ajustes</string>
|
||||
<string name="settings_category_title_ui">Interfaz de usuario</string>
|
||||
<string name="settings_display_barcode_max_brightness">Iluminar vista del código de barras</string>
|
||||
<string name="exportSuccessful">Datos de las tarjetas exportados</string>
|
||||
<string name="importSuccessful">Datos de las tarjetas importados</string>
|
||||
<string name="exportSuccessful">Datos exportados</string>
|
||||
<string name="importSuccessful">Datos importados</string>
|
||||
<string name="intent_import_card_from_url_share_text">Quiero compartirte una tarjeta</string>
|
||||
<string name="settings_dark_theme">Oscuro</string>
|
||||
<string name="settings_light_theme">Claro</string>
|
||||
<string name="settings_system_theme">Sistema</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="enterBarcodeInstructions">Introduzca el identificador de tarjeta y seleccione el código de barras que se utilizará, o de lo contrario, elija «Esta tarjeta no tiene código de barras».</string>
|
||||
<string name="enterBarcodeInstructions">Introduzca el código, y elija un tipo de código de barras a continuación, o «No hay código de barras».</string>
|
||||
<string name="app_copyright_old">Basado en Loyalty Card Keychain
|
||||
\nderechos de autor © 2016-2020 de Branden Archer.</string>
|
||||
\nderechos de autor © 2016-2020 de Branden Archer</string>
|
||||
<string name="exportOptionExplanation">Los datos se guardarán en la ubicación que elija.</string>
|
||||
<string name="failedParsingImportUriError">No se pudo procesar el URI de importación</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="barcodeNoBarcode">Esta tarjeta no tiene código de barras</string>
|
||||
<string name="barcodeNoBarcode">No hay código de barras</string>
|
||||
<string name="barcodeType">Tipo de código de barras</string>
|
||||
<string name="noMatchingGiftCards">Sin resultados. Pruebe modificando su búsqueda.</string>
|
||||
<string name="noMatchingGiftCards">Sin resultados. Intente cambiar su búsqueda.</string>
|
||||
<string name="action_search">Buscar</string>
|
||||
<string name="app_revision_fmt">Información de la revisión: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="noGroups">Primero pulse en el botón «+» para añadir grupos de categorización.</string>
|
||||
<string name="starImage">Favorito</string>
|
||||
<string name="thumbnailDescription">Miniatura de la tarjeta</string>
|
||||
<string name="copy_to_clipboard_toast">Se copió la id. de tarjeta en el portapapeles</string>
|
||||
<string name="noGroups">Pulse en el botón «+» para añadir grupos de categorización.</string>
|
||||
<string name="starImage">Estrella favorita</string>
|
||||
<string name="thumbnailDescription">Miniatura</string>
|
||||
<string name="copy_to_clipboard_toast">Se copió la ID en el portapapeles</string>
|
||||
<string name="selectBarcodeTitle">Seleccionar el código de barras</string>
|
||||
<string name="unstar">Eliminar de favoritos</string>
|
||||
<string name="noBarcode">Sin código de barras</string>
|
||||
<string name="enter_group_name">Introducir nombre del grupo</string>
|
||||
<string name="groups">Grupos</string>
|
||||
<string name="groupsList">Grupos: <xliff:g>%s</xliff:g></string>
|
||||
<string name="addManually">Introducir el id. de la tarjeta manualmente</string>
|
||||
<string name="addManually">Introducir la ID manualmente</string>
|
||||
<string name="leaveWithoutSaveConfirmation">¿Quiere abandonar sin guardar\?</string>
|
||||
<string name="leaveWithoutSaveTitle">Salir</string>
|
||||
<string name="moveDown">Bajar</string>
|
||||
@@ -85,6 +84,7 @@
|
||||
<string name="star">Añadir a favoritos</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> tarjeta</item>
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> tarjetas</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> tarjetas</item>
|
||||
</plurals>
|
||||
<string name="points">Puntos</string>
|
||||
@@ -98,26 +98,26 @@
|
||||
<string name="card">Tarjeta</string>
|
||||
<string name="expiryStateSentenceExpired">Expirado: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">Expira: <xliff:g>%s</xliff:g></string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Derechos de autor © 2019-<xliff:g>%d</xliff:g> de Sylvia van Os.</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Derechos de autor © 2019-<xliff:g>%d</xliff:g> de Sylvia van Os</string>
|
||||
<string name="app_resources">Recursos de terceros libres: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Bibliotecas de terceros libres: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="settings_max_font_size_scale">Tam. de fuente máximo</string>
|
||||
<string name="importCatimaMessage">Seleccione su <i>catima.zip</i> exportado desde Catima para importarlo.
|
||||
\nO créalo primero desde el menú Importar/Exportar de otra app de Catima al presionar Exportar desde allí.</string>
|
||||
\nCréalo primero desde el menú Importar/Exportar de otra app de Catima al presionar Exportar desde allí.</string>
|
||||
<string name="importFidmeMessage">Seleccione su <i>fidme-export-request-xxxxxx.zip</i> exportado desde FidMe para importar, y luego escoja los tipos de códigos de barras manualmente.
|
||||
\nO créalo primero desde tu perfil de FidMe eligiendo Protección de datos y pulsa Extraer mis datos.</string>
|
||||
\nCréalo primero desde tu perfil de FidMe eligiendo Protección de datos y pulsa Extraer mis datos.</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Seleccione su <i>LoyaltyCardKeychain.csv</i> exportado desde Loyalty Card Keychain para importarlo.
|
||||
\nO créalo primero desde el menú Importar/Exportar en Loyalty Card Keychain pulsando Exportar desde allí.</string>
|
||||
\nCréalo primero desde el menú Importar/Exportar en Loyalty Card Keychain pulsando Exportar desde allí.</string>
|
||||
<string name="importStocardMessage">Seleccione su exportación <i>*-sync.zip</i> de Stocard para importarla.
|
||||
\nO consígalo enviando un correo electrónico a support@stocardapp.com solicitando una exportación de sus datos.</string>
|
||||
\nConsígalo enviando un correo electrónico a support@stocardapp.com solicitando una exportación de sus datos.</string>
|
||||
<string name="importVoucherVaultMessage">Seleccione su <i>vouchervault.json</i> exportado desde Voucher Vault para importarlo.
|
||||
\nO créalo pulsando primero Exportar en Voucher Vault.</string>
|
||||
\nCréalo pulsando primero Exportar en Voucher Vault.</string>
|
||||
<string name="failedGeneratingShareURL">No se ha podido generar una URL compartible. Por favor, informe de ello.</string>
|
||||
<string name="passwordRequired">Por favor, introduzca la contraseña</string>
|
||||
<string name="updateBarcodeQuestionText">Ha cambiado la Id. de la tarjeta. ¿Desea actualizar también el código de barras para usar el mismo valor\?</string>
|
||||
<string name="updateBarcodeQuestionText">Ha cambiado el código. ¿Desea actualizar también el código de barras para usar el mismo valor\?</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Quiero compartirte algunas tarjetas</string>
|
||||
<string name="setBackImage">Establecer imagen anversa</string>
|
||||
<string name="card_ids_copied">Id. de tarjetas copiadas</string>
|
||||
<string name="card_ids_copied">Código(s) copiado(s)</string>
|
||||
<string name="turn_flashlight_off">Apagar linterna</string>
|
||||
<string name="turn_flashlight_on">Encender linterna</string>
|
||||
<string name="no">No</string>
|
||||
@@ -127,13 +127,13 @@
|
||||
<string name="removeImage">Quitar imagen</string>
|
||||
<string name="setFrontImage">Establecer imagen frontal</string>
|
||||
<string name="photos">Fotos</string>
|
||||
<string name="backImageDescription">Imagen del reverso de la tarjeta</string>
|
||||
<string name="frontImageDescription">Imagen frontal de la tarjeta</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID de tarjetas copiadas al portapapeles</string>
|
||||
<string name="backImageDescription">Imagen del reverso</string>
|
||||
<string name="frontImageDescription">Imagen frontal</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">Códigos copiados al portapapeles</string>
|
||||
<string name="wrongValueForBarcodeType">El valor no es válido para el tipo de código de barras seleccionado</string>
|
||||
<string name="unsupportedBarcodeType">Este tipo de código de barras todavía no se puede visualizar. Es posible que se admita en una futura versión de la aplicación.</string>
|
||||
<string name="setBarcodeId">Establecer valor de código de barra</string>
|
||||
<string name="sameAsCardId">Igual que la ID de tarjeta</string>
|
||||
<string name="sameAsCardId">Igual que el código</string>
|
||||
<string name="barcodeId">Valor de código de barra</string>
|
||||
<string name="importVoucherVault">Importar desde Voucher Vault</string>
|
||||
<string name="importStocard">Importar desde Stocard</string>
|
||||
@@ -145,8 +145,8 @@
|
||||
\n
|
||||
\nNINGÚN DATO SE RECOPILA, cualquiera puede confirmar ya que nuestra aplicación es software libre.</string>
|
||||
<string name="privacy_policy">Política de privacidad</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="chooseImportType">¿De dónde importar datos\?</string>
|
||||
<string name="app_loyalty_card_keychain">Llavero con tarjeta de fidelización</string>
|
||||
<string name="chooseImportType">Importar datos de</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> no tendría un saldo válido.</string>
|
||||
<string name="currency">Moneda</string>
|
||||
<string name="balance">Saldo</string>
|
||||
@@ -154,20 +154,23 @@
|
||||
<string name="noBarcodeFound">No se encontró código de barras</string>
|
||||
<string name="balanceSentence">Saldo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="addFromImage">Selecciona imagen desde galería</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Evitar bloqueo de pantalla</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Evitar el bloqueo de pantalla</string>
|
||||
<string name="settings_keep_screen_on">Mantener pantalla encendida</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> tarjeta seleccionada</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> tarjetas seleccionadas</item>
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> seleccionada</item>
|
||||
<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="deleteConfirmation">¿Quiere eliminar esta 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>
|
||||
<item quantity="many">¿Borrar estas tarjetas <xliff:g>%d</xliff:g> permanentemente\?</item>
|
||||
<item quantity="other">¿Borrar estas tarjetas <xliff:g>%d</xliff:g> permanentemente\?</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Borrar <xliff:g>%d</xliff:g> tarjeta</item>
|
||||
<item quantity="many">Borrar <xliff:g>%d</xliff:g> tarjetas</item>
|
||||
<item quantity="other">Borrar <xliff:g>%d</xliff:g> tarjetas</item>
|
||||
</plurals>
|
||||
<string name="app_contributors">Hecho posible por: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
@@ -183,5 +186,93 @@
|
||||
<string name="settings_catima_theme">Catima</string>
|
||||
<string name="settings_system_locale">Sistema</string>
|
||||
<string name="settings_locale">Lengua</string>
|
||||
<string name="noGroupCards">Este grupo no contiene ninguna tarjeta</string>
|
||||
<string name="noGroupCards">Este grupo está vacío</string>
|
||||
<string name="settings_landscape_orientation">Horizontal</string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> punto</item>
|
||||
<item quantity="many"><xliff:g>%s</xliff:g> puntos</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> puntos</item>
|
||||
</plurals>
|
||||
<string name="barcodeImageDescriptionWithType">Imagen <xliff:g>%s</xliff:g> código de barras</string>
|
||||
<string name="settings_card_orientation">Orientación del código de barras</string>
|
||||
<string name="settings_portrait_orientation">Formato vertical</string>
|
||||
<string name="group_edit">Editar grupo</string>
|
||||
<string name="group_updated">Grupo actualizado</string>
|
||||
<string name="noGiftCardsGroup">Cree algunas tarjetas y luego asígnelas al grupo aquí.</string>
|
||||
<string name="settings_follow_system_orientation">Seguir el sistema</string>
|
||||
<string name="settings_lock_on_opening_orientation">Bloqueo a la orientación utilizada al abrir la tarjeta</string>
|
||||
<string name="sort_by_most_recently_used">Lo más reciente que se ha utilizado</string>
|
||||
<string name="sort_by_expiry">Caducidad</string>
|
||||
<string name="sort_by_balance">Saldo</string>
|
||||
<string name="version_history">Historial de versiones</string>
|
||||
<string name="help_translate_this_app">Ayuda a traducir esta aplicación</string>
|
||||
<string name="and_data_usage">y el uso de datos</string>
|
||||
<string name="shortcutSelectCard">Seleccione una tarjeta</string>
|
||||
<string name="showMoreInfo">Mostrar información</string>
|
||||
<string name="hideMoreInfo">Ocultar información</string>
|
||||
<string name="reverse">… en orden inverso</string>
|
||||
<string name="credits">Créditos</string>
|
||||
<string name="sort_by_name">Nombre</string>
|
||||
<string name="license">Licencia</string>
|
||||
<string name="source_repository">Repositorio de fuente</string>
|
||||
<string name="set_scale">Ajustar la escala</string>
|
||||
<string name="on_github">En GitHub</string>
|
||||
<string name="on_google_play">en Google Play</string>
|
||||
<string name="report_error">Informar de un error</string>
|
||||
<string name="action_hide_details">Ocultar detalles</string>
|
||||
<string name="translate_platform">en Weblate</string>
|
||||
<string name="action_show_details">Mostrar detalles</string>
|
||||
<string name="selectColor">Seleccione el color</string>
|
||||
<string name="setIcon">Establecer icono</string>
|
||||
<string name="sort">Ordenar</string>
|
||||
<string name="swipeToSwitchImages">Desliza para cambiar de imagen, mantén presionado para abrir la imagen en la aplicación de la galería</string>
|
||||
<string name="sort_by">Ordenar por</string>
|
||||
<string name="rate_this_app">Califica esta aplicación</string>
|
||||
<string name="options">Opciones</string>
|
||||
<string name="failedToOpenUrl">Instale primero un navegador web</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Ver archivo (<xliff:g>%1$d</xliff:g> tarjeta)</item>
|
||||
<item quantity="many">Ver archivo (<xliff:g>%1$d</xliff:g> tarjetas)</item>
|
||||
<item quantity="other">Ver archivo (<xliff:g>%1$d</xliff:g> tarjetas)</item>
|
||||
</plurals>
|
||||
<string name="welcome">Bienvenido/a a Catima</string>
|
||||
<string name="group_name_already_in_use">Nombre del grupo ya está en uso</string>
|
||||
<string name="group_name_is_empty">El nombre del grupo no puede estar vacío</string>
|
||||
<string name="settings_oled_dark">Fondo negro puro para el tema oscuro</string>
|
||||
<string name="exportPasswordHint">Introduzca la contraseña</string>
|
||||
<string name="previousCard">Anterior</string>
|
||||
<string name="nextCard">Siguiente</string>
|
||||
<string name="editGroup">Edición del grupo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="include_if_asking_support">Si desea solicitar apoyo, incluya la siguiente información:</string>
|
||||
<string name="duplicateCard">Duplicar</string>
|
||||
<string name="unarchive">Desarchivar</string>
|
||||
<string name="archive">Archivar</string>
|
||||
<string name="archived">Tarjeta archivada</string>
|
||||
<string name="unarchived">Tarjeta desarchivada</string>
|
||||
<string name="archiveList">Archivo</string>
|
||||
<string name="noUnarchivedCardsMessage">No existen tarjetas sin archivar</string>
|
||||
<string name="exportPassword">Establezca una contraseña para proteger su exportación (opcional)</string>
|
||||
<string name="failedLaunchingPhotoPicker">No se ha podido encontrar una aplicación de galería compatible</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> tarjeta (archivada)<xliff:g id="archivedCount">%2$d</xliff:g></item>
|
||||
<item quantity="many"><xliff:g>%1$d</xliff:g> tarjetas (archivadas)<xliff:g id="archivedCount">%2$d</xliff:g></item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> tarjetas (archivadas)<xliff:g id="archivedCount">%2$d</xliff:g></item>
|
||||
</plurals>
|
||||
<string name="starred">Estrellado</string>
|
||||
<string name="failedToRetrieveImageFile">No se pudo recuperar el archivo de imagen</string>
|
||||
<string name="barcodeLongPressMessage">Solo se pueden abrir imágenes en la aplicación de galería</string>
|
||||
<string name="updateBalanceTitle">¿Cuánto has gastado\?</string>
|
||||
<string name="currentBalanceSentence">Saldo actual: <xliff:g>%s</xliff:g></string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Para escanear códigos de barras, Catima necesitará acceso a su cámara. Toque aquí para cambiar la configuración de sus permisos.</string>
|
||||
<string name="updateBalanceHint">Introduzca el importe</string>
|
||||
<string name="newBalanceSentence">Nuevo balance: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">No se pudo acceder a la cámara</string>
|
||||
<string name="updateBalance">Actualizar el balance</string>
|
||||
<string name="importCards">Importar tarjetas</string>
|
||||
<string name="storageReadPermissionRequired">Se necesita permiso para leer el almacenamiento para esta acción…</string>
|
||||
<string name="cameraPermissionRequired">Se necesita permiso para acceder a la cámara para esta acción…</string>
|
||||
<string name="anyDate">Cualquier fecha</string>
|
||||
<string name="validFromDate">Válido desde</string>
|
||||
<string name="chooseValidFromDate">Elija una fecha válida desde</string>
|
||||
<string name="validFromSentence">Válido desde: <xliff:g>%s</xliff:g></string>
|
||||
</resources>
|
||||
@@ -1,10 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="noExternalStoragePermissionError">Salli käyttöoikeus ulkoisen tallennustilan käyttöön voidaksesi tuoda tai viedä tietoja</string>
|
||||
<string name="no">Ei</string>
|
||||
<string name="yes">Kyllä</string>
|
||||
<string name="updateBarcodeQuestionText">Vaihdoit ID-tunnuksen. Haluatko päivittää myös viivakoodin käyttämään samaa arvoa\?</string>
|
||||
<string name="updateBarcodeQuestionTitle">Päivitä viivakoodin arvo\?</string>
|
||||
<string name="updateBarcodeQuestionTitle">Päivitetäänkö viivakoodin arvo\?</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Haluan jakaa joitain kortteja kanssasi</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID-tunnukset kopioitu leikepöydälle</string>
|
||||
<string name="wrongValueForBarcodeType">Arvo ei ole kelvollinen valitulle viivakoodityypille</string>
|
||||
@@ -14,15 +13,15 @@
|
||||
<string name="barcodeId">Viivakoodin arvo</string>
|
||||
<string name="importVoucherVaultMessage">Valitse tuotava <i>vouchervault.json</i>-vienti Voucher Vaultista.
|
||||
\nLuo se painamalla ensin Vie Voucher Vaultissa.</string>
|
||||
<string name="importVoucherVault">Tuo Voucher Vault varmuuskopiotiedostosta</string>
|
||||
<string name="importVoucherVault">Tuo Voucher Vault -varmuuskopiotiedostosta</string>
|
||||
<string name="importLoyaltyCardKeychainMessage">Valitse tuotava <i>LoyaltyCardKeychain.csv</i>-vientitiedostosi Loyalty Card Keychainista.
|
||||
\nTai luo se Loyalty Card Keychainin Import/Export-valikosta painamalla ensin Export (Vie).</string>
|
||||
<string name="importLoyaltyCardKeychain">Tuo Loyalty Card Keychain varmuuskopiotiedostosta</string>
|
||||
<string name="importFidmeMessage">Valitse tuotava <i>fidme-export-request-xxxxxxxx.zip</i>-vientitiedostosi FidMe:stä ja valitse viivakoodityypit manuaalisesti sen jälkeen.
|
||||
\nLuo se FidMe-profiilistasi valitsemalla Tietosuoja ja painamalla ensin Extract my data.</string>
|
||||
<string name="importFidme">Tuo FidMe varmuuskopiotiedostosta</string>
|
||||
<string name="importFidme">Tuo FidMe-varmuuskopiotiedostosta</string>
|
||||
<string name="importCatimaMessage">Valitse tuotava <i>catima.zip</i>-vientitiedostosi Catimasta.
|
||||
\nLuo se Catima-sovelluksen Tuo/Vie-valikosta painamalla siellä ensin Vie.</string>
|
||||
\nLuo se Catima-sovelluksen Tuo/vie-valikosta painamalla siellä ensin Vie.</string>
|
||||
<string name="importCatima">Tuo Catima varmuuskopiotiedostosta</string>
|
||||
<string name="accept">Hyväksy</string>
|
||||
<string name="privacy_policy_popup_text">Tietosuojaseloste (joidenkin sovelluskauppojen vaatimus):
|
||||
@@ -51,18 +50,18 @@
|
||||
<string name="groupsList">Ryhmät: <xliff:g>%s</xliff:g></string>
|
||||
<string name="addFromImage">Valitse kuva galleriasta</string>
|
||||
<string name="addManually">Anna ID-tunnus manuaalisesti</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Poistu tallentamatta\?</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Poistutaanko tallentamatta\?</string>
|
||||
<string name="leaveWithoutSaveTitle">Poistu</string>
|
||||
<string name="moveDown">Siirrä alaspäin</string>
|
||||
<string name="moveUp">Siirrä ylöspäin</string>
|
||||
<string name="failedOpeningFileManager">Asenna ensin tiedostonhallintaohjelma.</string>
|
||||
<string name="deleteConfirmationGroup">Poista ryhmä\?</string>
|
||||
<string name="deleteConfirmationGroup">Poistetaanko ryhmä\?</string>
|
||||
<string name="all">Kaikki</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> kortti</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kortit</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> korttia</item>
|
||||
</plurals>
|
||||
<string name="noGroups">Napsauta + plus-painiketta lisätäksesi ryhmät luokittelua varten.</string>
|
||||
<string name="noGroups">Napsauta plus-painiketta (+) lisätäksesi ryhmät luokittelua varten.</string>
|
||||
<string name="groups">Ryhmät</string>
|
||||
<string name="enter_group_name">Anna ryhmän nimi</string>
|
||||
<string name="exportSuccessful">Tiedot viety</string>
|
||||
@@ -78,18 +77,18 @@
|
||||
<string name="settings_theme">Teema</string>
|
||||
<string name="settings_category_title_ui">Käyttöliittymä</string>
|
||||
<string name="settings">Asetukset</string>
|
||||
<string name="starImage">Suosikki tähti</string>
|
||||
<string name="starImage">Suosikkitähti</string>
|
||||
<string name="thumbnailDescription">Pienoiskuva</string>
|
||||
<string name="copy_to_clipboard_toast">ID-tunnus kopioitu leikepöydälle</string>
|
||||
<string name="enterBarcodeInstructions">Syötä ID-tunnus ja valitse sen viivakoodityyppi, tai valitse \"Ei viivakoodia\".</string>
|
||||
<string name="selectBarcodeTitle">Valitse viivakoodi</string>
|
||||
<string name="app_resources">Vapaat kolmannen osapuolen resurssit: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Kolmannen osapuolen Libre-kirjastot: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_libraries">Vapaat kolmannen osapuolen kirjastot: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Muutostiedot: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versio: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="about_title_fmt">Tietoja <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="app_license">Copyleft (käyttäjänoikeus) - vapaa ohjelmisto, lisenssi GPLv3+</string>
|
||||
<string name="app_copyright_old">Perustuu Loyalty Card Keychain sovellukseen
|
||||
<string name="app_copyright_old">Perustuu Loyalty Card Keychain -sovellukseen
|
||||
\ntekijänoikeus © 2016–2020 Branden Archer</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">Tekijänoikeus © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<string name="about">Tietoja</string>
|
||||
@@ -110,7 +109,7 @@
|
||||
<string name="importSuccessfulTitle">Tuonti valmis</string>
|
||||
<string name="importExportHelp">Tietojesi varmuuskopiointi mahdollistaa niiden siirtämisen toiseen laitteeseen.</string>
|
||||
<string name="exportName">Vie</string>
|
||||
<string name="importExport">Tuo/Vie</string>
|
||||
<string name="importExport">Tuo/vie</string>
|
||||
<string name="failedParsingImportUriError">Tuonnin URI: n jäsentäminen epäonnistui</string>
|
||||
<string name="noCardExistsError">Tätä korttia ei löytynyt</string>
|
||||
<string name="noCardIdError">ID-tunnusta ei annettu</string>
|
||||
@@ -139,7 +138,7 @@
|
||||
<string name="note">Lisätieto</string>
|
||||
<string name="storeName">Nimi</string>
|
||||
<string name="noMatchingGiftCards">Ei hakutuloksia, kokeile toisella hakutermillä.</string>
|
||||
<string name="noGiftCards">Lisää kortti napsauttamalla + plus-painiketta, tai mene ⋮ valikkoon tuodaksesi varmuuskopiosta.</string>
|
||||
<string name="noGiftCards">Lisää kortti napsauttamalla plus-painiketta (+), tai mene ⋮-valikkoon tuodaksesi.</string>
|
||||
<string name="action_add">Lisää</string>
|
||||
<string name="action_search">Hae</string>
|
||||
<string name="takePhoto">Ota valokuva</string>
|
||||
@@ -149,32 +148,32 @@
|
||||
<string name="photos">Valokuvat</string>
|
||||
<string name="backImageDescription">Takakuva</string>
|
||||
<string name="frontImageDescription">Etukuva</string>
|
||||
<string name="deleteConfirmation">Poista tämä kortti\?</string>
|
||||
<string name="deleteConfirmation">Poistetaanko tämä kortti\?</string>
|
||||
<string name="deleteTitle">Poista kortti</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Poista tämä <xliff:g>%d</xliff:g> kortti pysyvästi\?</item>
|
||||
<item quantity="other">Poista tämä <xliff:g>%d</xliff:g> kortit pysyvästi\?</item>
|
||||
<item quantity="one">Poistetaanko tämä <xliff:g>%d</xliff:g> kortti pysyvästi\?</item>
|
||||
<item quantity="other">Poistetaanko nämä <xliff:g>%d</xliff:g> korttia pysyvästi\?</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Poista <xliff:g>%d</xliff:g>kortti</item>
|
||||
<item quantity="other">Poista <xliff:g>%d</xliff:g>kortit</item>
|
||||
<item quantity="other">Poista <xliff:g>%d</xliff:g>korttia</item>
|
||||
</plurals>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> valittu</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> valitut</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> valittu</item>
|
||||
</plurals>
|
||||
<string name="importStocard">Tuo Stocardista</string>
|
||||
<string name="importStocardMessage">Valitse tuotava <i>***-sync.zip</i>-vienti Stocardista.
|
||||
\nHanki se lähettämällä sähköpostia osoitteeseen support@stocardapp.com ja pyytämällä tietojesi vientiä.</string>
|
||||
<string name="passwordRequired">Ole hyvä ja syötä salasana</string>
|
||||
<string name="failedGeneratingShareURL">Ei pystynyt luomaan jaettavaa URL-osoitetta. Ilmoita tästä.</string>
|
||||
<string name="turn_flashlight_on">Sytytä taskulamppu</string>
|
||||
<string name="failedGeneratingShareURL">Jaettavaa URL-osoitetta ei voitu luoda. Ilmoita tästä.</string>
|
||||
<string name="turn_flashlight_on">Käytä taskulamppua</string>
|
||||
<string name="turn_flashlight_off">Sammuta salamavalo</string>
|
||||
<string name="app_contributors">Mahdollistanut: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="settings_brown_theme">Ruskea</string>
|
||||
<string name="settings_grey_theme">Harmaa</string>
|
||||
<string name="settings_green_theme">Vihreä</string>
|
||||
<string name="settings_sky_blue_theme">Taivaan sininen</string>
|
||||
<string name="settings_sky_blue_theme">Taivaansininen</string>
|
||||
<string name="settings_blue_theme">Siniset</string>
|
||||
<string name="settings_violet_theme">Violetti</string>
|
||||
<string name="settings_magenta_theme">Magenta</string>
|
||||
@@ -195,7 +194,7 @@
|
||||
</plurals>
|
||||
<string name="settings_oled_dark">Musta tausta tummalle teemalle</string>
|
||||
<string name="setIcon">Aseta kuvake</string>
|
||||
<string name="swipeToSwitchImages">Vaihda kuvia pyyhkäisemällä tai painamalla pitkään</string>
|
||||
<string name="swipeToSwitchImages">Vaihda kuvia pyyhkäisemällä, paina kuvaa pitkään avataksesi galleriasovelluksessa</string>
|
||||
<string name="sort_by_name">Nimi</string>
|
||||
<string name="sort_by_most_recently_used">Viimeksi käytetyt</string>
|
||||
<string name="sort_by_expiry">Viimeinen voimassaoloaika</string>
|
||||
@@ -227,5 +226,46 @@
|
||||
<string name="selectColor">Valitse väri</string>
|
||||
<string name="rate_this_app">Arvostele tämä sovellus</string>
|
||||
<string name="noGiftCardsGroup">Lisää kortteja ja lisää ne ryhmään täällä.</string>
|
||||
<string name="barcodeImageDescriptionWithType">Image <xliff:g>%s</xliff:g> viivakoodi</string>
|
||||
<string name="barcodeImageDescriptionWithType">Kuva <xliff:g>%s</xliff:g> viivakoodi</string>
|
||||
<string name="settings_follow_system_orientation">Seuraa järjestelmää</string>
|
||||
<string name="settings_portrait_orientation">Pysty</string>
|
||||
<string name="settings_landscape_orientation">Vaaka</string>
|
||||
<string name="unarchived">Kortti on poistettu arkistosta</string>
|
||||
<string name="noUnarchivedCardsMessage">Arkistoimattomia kortteja ei ole olemassa</string>
|
||||
<string name="unarchive">Poista arkistosta</string>
|
||||
<string name="archived">Kortti arkistoitu</string>
|
||||
<string name="failedLaunchingPhotoPicker">Tuettua galleriasovellusta ei löytynyt</string>
|
||||
<string name="settings_card_orientation">Viivakoodin suuntaus</string>
|
||||
<string name="archiveList">Arkisto</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> kortti (<xliff:g id="archivedCount">%2$d</xliff:g> arkistoitu)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> korttia (<xliff:g id="archivedCount">%2$d</xliff:g> arkistoitu)</item>
|
||||
</plurals>
|
||||
<string name="duplicateCard">Kaksoiskappale</string>
|
||||
<string name="previousCard">Edellinen</string>
|
||||
<string name="nextCard">Seuraava</string>
|
||||
<string name="failedToOpenUrl">Asenna ensin verkkoselain</string>
|
||||
<string name="welcome">Tervetuloa Catimaan</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Näytä arkisto (<xliff:g>%1$d</xliff:g> kortti)</item>
|
||||
<item quantity="other">Näytä arkisto (<xliff:g>%1$d</xliff:g> korttia)</item>
|
||||
</plurals>
|
||||
<string name="updateBalanceTitle">Kuinka paljon kulutit\?</string>
|
||||
<string name="updateBalanceHint">Syötä summa</string>
|
||||
<string name="barcodeLongPressMessage">Vain kuvia on mahdollista avata galleriasovelluksessa</string>
|
||||
<string name="archive">Arkistoi</string>
|
||||
<string name="importCards">Tuo kortteja</string>
|
||||
<string name="failedToRetrieveImageFile">Kuvatiedoston noutaminen epäonnistui</string>
|
||||
<string name="currentBalanceSentence">Nykyinen saldo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="newBalanceSentence">Uusi saldo: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">Ei pääsyä kameraan</string>
|
||||
<string name="settings_lock_on_opening_orientation">Lukitse suunta, kun korttia avataan</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Viivakoodien lukeminen vaatii, että Catimalla on käyttöoikeus kameraan. Napauta tästä muuttaaksesi oikeuksia.</string>
|
||||
<string name="updateBalance">Päivitä saldo</string>
|
||||
<string name="cameraPermissionRequired">Tämä toiminto vaatii oikeuden käyttää kameraa…</string>
|
||||
<string name="storageReadPermissionRequired">Tämä toiminto vaatii oikeuden lukea tallennustilaa…</string>
|
||||
<string name="validFromDate">Kelvollinen alkaen</string>
|
||||
<string name="anyDate">Mikä tahansa päivämäärä</string>
|
||||
<string name="chooseValidFromDate">Valitse kelvollinen päivämäärä</string>
|
||||
<string name="validFromSentence">Kelvollinen alkaen: <xliff:g>%s</xliff:g></string>
|
||||
</resources>
|
||||
@@ -32,7 +32,6 @@
|
||||
<string name="exportFailed">Impossible d’effectuer l’exportation</string>
|
||||
<string name="importing">Import …</string>
|
||||
<string name="exporting">Export …</string>
|
||||
<string name="noExternalStoragePermissionError">Accorder au stockage externe l’autorisation d’importer ou d’exporter des données</string>
|
||||
<string name="importOptionFilesystemTitle">Importer depuis le système de fichiers</string>
|
||||
<string name="importOptionFilesystemExplanation">Choisissez le fichier à importer.</string>
|
||||
<string name="importOptionFilesystemButton">Système de fichiers</string>
|
||||
@@ -84,6 +83,7 @@
|
||||
<string name="moveUp">Monter</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> carte</item>
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> cartes</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> cartes</item>
|
||||
</plurals>
|
||||
<string name="groupsList">Groupes : <xliff:g>%s</xliff:g></string>
|
||||
@@ -96,7 +96,7 @@
|
||||
<string name="chooseImportType">Importer les données depuis</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">%s</xliff:g> ne semble pas être un solde valide.</string>
|
||||
<string name="points">Points</string>
|
||||
<string name="currency">Monnaie</string>
|
||||
<string name="currency">Devise</string>
|
||||
<string name="balance">Solde</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">Centrer le code-barres sur l’écran</string>
|
||||
<string name="moveBarcodeToTopOfScreen">Déplacez le code-barres vers le haut de l’écran</string>
|
||||
@@ -158,16 +158,19 @@
|
||||
<string name="failedGeneratingShareURL">Impossible de générer une URL partageable. Veuillez signaler ceci.</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> sélectionnée</item>
|
||||
<item quantity="many"><xliff:g>%d</xliff:g> sélectionnées</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> sélectionnées</item>
|
||||
</plurals>
|
||||
<string name="deleteTitle">Supprimer la carte</string>
|
||||
<string name="deleteConfirmation">Supprimer cette carte \?</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">Supprimer cette <xliff:g>%d</xliff:g> carte définitivement \?</item>
|
||||
<item quantity="many">Supprimer ces <xliff:g>%d</xliff:g> cartes définitivement \?</item>
|
||||
<item quantity="other">Supprimer ces <xliff:g>%d</xliff:g> cartes définitivement \?</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">Supprimer <xliff:g>%d</xliff:g> carte</item>
|
||||
<item quantity="many">Supprimer <xliff:g>%d</xliff:g> cartes</item>
|
||||
<item quantity="other">Supprimer <xliff:g>%d</xliff:g> cartes</item>
|
||||
</plurals>
|
||||
<string name="settings_system_locale">Système</string>
|
||||
@@ -185,7 +188,7 @@
|
||||
<string name="app_contributors">Rendu possible par : <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="noGroupCards">Ce groupe est vide</string>
|
||||
<string name="barcodeImageDescriptionWithType">Image <xliff:g>%s</xliff:g> code-barres</string>
|
||||
<string name="swipeToSwitchImages">Balayez ou appuyez longuement pour changer d’image</string>
|
||||
<string name="swipeToSwitchImages">Balayez pour changer d’image, maintenez appuyé pour ouvrir l’image dans la galerie</string>
|
||||
<string name="sort">Trier</string>
|
||||
<string name="sort_by">Trier par</string>
|
||||
<string name="reverse">… dans l’ordre inverse</string>
|
||||
@@ -224,6 +227,7 @@
|
||||
<string name="hideMoreInfo">Masquer les infos</string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> point</item>
|
||||
<item quantity="many"><xliff:g>%s</xliff:g> points</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> points</item>
|
||||
</plurals>
|
||||
<string name="settings_oled_dark">Fond noir pour le thème sombre</string>
|
||||
@@ -240,4 +244,35 @@
|
||||
<string name="unarchived">Carte désarchivée</string>
|
||||
<string name="archiveList">Archives</string>
|
||||
<string name="noUnarchivedCardsMessage">Il n\'existe aucune carte non archivée</string>
|
||||
</resources>
|
||||
<string name="failedLaunchingPhotoPicker">Impossible de trouver une application de galerie prise en charge</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> carte (<xliff:g id="archivedCount">%2$d</xliff:g> archivée)</item>
|
||||
<item quantity="many"><xliff:g>%1$d</xliff:g> cartes (<xliff:g id="archivedCount">%2$d</xliff:g> archivées)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> cartes (<xliff:g id="archivedCount">%2$d</xliff:g> archivées)</item>
|
||||
</plurals>
|
||||
<string name="nextCard">Suivant</string>
|
||||
<string name="previousCard">Précédent</string>
|
||||
<string name="failedToOpenUrl">Installez d\'abord un navigateur web</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Voir les archives (<xliff:g>%1$d</xliff:g> carte)</item>
|
||||
<item quantity="many">Voir les archives (<xliff:g>%1$d</xliff:g> cartes)</item>
|
||||
<item quantity="other">Voir les archives (<xliff:g>%1$d</xliff:g> cartes)</item>
|
||||
</plurals>
|
||||
<string name="welcome">Bienvenue dans Catima</string>
|
||||
<string name="barcodeLongPressMessage">Seules les images peuvent être ouvertes dans l’application galerie</string>
|
||||
<string name="failedToRetrieveImageFile">Impossible de récupérer le fichier image</string>
|
||||
<string name="currentBalanceSentence">Solde actuel : <xliff:g>%s</xliff:g></string>
|
||||
<string name="updateBalanceHint">Entrez le montant</string>
|
||||
<string name="cameraPermissionDeniedTitle">Impossible d\'accéder à la caméra</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Pour scanner les codes-barres, Catima doit avoir accès à votre caméra. Tapez ici pour modifier vos paramètres d\'autorisation.</string>
|
||||
<string name="updateBalance">Mettre à jour le solde</string>
|
||||
<string name="updateBalanceTitle">Combien avez-vous dépensé \?</string>
|
||||
<string name="newBalanceSentence">Nouveau solde : <xliff:g>%s</xliff:g></string>
|
||||
<string name="importCards">Importer des cartes</string>
|
||||
<string name="storageReadPermissionRequired">L\'autorisation de lire le stockage est nécessaire pour cette action…</string>
|
||||
<string name="cameraPermissionRequired">L\'autorisation d\'accéder à la caméra est nécessaire pour cette action…</string>
|
||||
<string name="validFromDate">Valide à partir de</string>
|
||||
<string name="validFromSentence">Valide à partir de : <xliff:g>%s</xliff:g></string>
|
||||
<string name="anyDate">N’importe quelle date</string>
|
||||
<string name="chooseValidFromDate">Choisissez la date de début de validité</string>
|
||||
</resources>
|
||||
@@ -39,7 +39,6 @@
|
||||
<string name="cardShortcut">קיצור דרך</string>
|
||||
<string name="noCardsMessage">תחילה הוסף כרטיס</string>
|
||||
<string name="card_ids_copied">מזהי כרטיס הועתקו</string>
|
||||
<string name="barcodeImageDescriptionWithType"></string>
|
||||
<string name="noStoreError">לא הוכנס שם חנות</string>
|
||||
<string name="noCardExistsError">כרטיס לא נמצא</string>
|
||||
<string name="importExport">ייבוא/ייצוא</string>
|
||||
@@ -52,4 +51,19 @@
|
||||
<string name="exportFailedTitle">הייצוא נכשל</string>
|
||||
<string name="importing">מייבא…</string>
|
||||
<string name="exporting">ייצוא…</string>
|
||||
<string name="exportOptionExplanation">המידע יכתב למיקום שאת/ה תבחר/י.</string>
|
||||
<string name="importOptionFilesystemTitle">יבא ממערכת קבצים</string>
|
||||
<string name="importOptionFilesystemExplanation">בחר/י קובץ מסויים ממערכת הקבצים.</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">אחד</item>
|
||||
<item quantity="two">שניים</item>
|
||||
<item quantity="many">מעט</item>
|
||||
<item quantity="other">אחר</item>
|
||||
</plurals>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">אחד</item>
|
||||
<item quantity="two">שניים</item>
|
||||
<item quantity="many">מעט</item>
|
||||
<item quantity="other">אחר</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
153
app/src/main/res/values-hi/strings.xml
Normal file
153
app/src/main/res/values-hi/strings.xml
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="storeName">नाम</string>
|
||||
<string name="note">नोट</string>
|
||||
<string name="cardId">कार्ड आईडी</string>
|
||||
<string name="star">पसंदीदा में जोड़ें</string>
|
||||
<string name="unstar">पसंदीदा से निकाले</string>
|
||||
<string name="cancel">रद्द करना</string>
|
||||
<string name="save">बचाना</string>
|
||||
<string name="delete">मिटाना</string>
|
||||
<string name="deleteConfirmation">इस कार्ड को स्थायी रूप से हटाएं\?</string>
|
||||
<plurals name="deleteCardsConfirmation">
|
||||
<item quantity="one">इस <xliff:g>%d</xliff:g> कार्ड को स्थायी रूप से हटाएं\?</item>
|
||||
<item quantity="other">ये <xliff:g>%d</xliff:g> कार्ड स्थायी रूप से हटाएं\?</item>
|
||||
</plurals>
|
||||
<string name="ok">ठीक</string>
|
||||
<string name="share">बाँटें</string>
|
||||
<string name="sendLabel">भेजें…</string>
|
||||
<string name="editCardTitle">कार्ड संपादित करें</string>
|
||||
<string name="addCardTitle">कार्ड जोड़ें</string>
|
||||
<string name="noCardsMessage">पहले एक कार्ड जोड़ें</string>
|
||||
<string name="card_ids_copied">कॉपी की गई आईडी</string>
|
||||
<string name="noStoreError">कोई नाम दर्ज नहीं</string>
|
||||
<string name="noCardIdError">कोई पहचान पत्र (आईडी दर्ज नहीं) की गई</string>
|
||||
<string name="noCardExistsError">वह कार्ड नहीं मिला</string>
|
||||
<string name="importExport">आयात / निर्यात</string>
|
||||
<string name="exportName">निर्यात</string>
|
||||
<string name="importSuccessfulTitle">आयातित</string>
|
||||
<string name="importFailed">आयात नहीं कर सका</string>
|
||||
<string name="action_search">खोज</string>
|
||||
<string name="noGiftCardsGroup">कुछ कार्ड बनाएँ, और फिर उन्हें यहाँ समूह करें।</string>
|
||||
<string name="noMatchingGiftCards">कोई परिणाम नहीं। अपनी खोज बदलने का प्रयास करें।</string>
|
||||
<string name="deleteTitle">कार्ड हटाएं</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one">कार्ड <xliff:g>%d</xliff:g> हटाएं</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> इन कार्डों को हटाएं</item>
|
||||
</plurals>
|
||||
<string name="importFailedTitle">आयात विफल</string>
|
||||
<string name="exportOptionExplanation">डाटा आपके मनचाहे स्थान पर लिखा जाएगा.</string>
|
||||
<string name="importOptionFilesystemExplanation">फाईल सिस्टम से एक फाईल चुनें.</string>
|
||||
<string name="app_copyright_old">लोयलटी कार्ड कीचैंन पर आधारित
|
||||
\nकौपीराईट © 2016–2020 ब्रांडन आर्चर</string>
|
||||
<string name="action_add">जोड़</string>
|
||||
<string name="edit">बदलें</string>
|
||||
<string name="confirm">पक्का करें</string>
|
||||
<string name="failedParsingImportUriError">दी गई URL का विक्ष्लेषण नही हो सका</string>
|
||||
<string name="exportSuccessfulTitle">निर्यात सफल</string>
|
||||
<string name="exportFailedTitle">निर्यात असफल</string>
|
||||
<string name="exportFailed">निर्यात नही हो सका</string>
|
||||
<string name="importing">आयात चल रहा है…</string>
|
||||
<string name="exporting">निर्यात चल रहा है…</string>
|
||||
<string name="importOptionFilesystemTitle">फाईल सिस्टम से आयात करें</string>
|
||||
<string name="importOptionFilesystemButton">फाईल सिस्टम से</string>
|
||||
<string name="importOptionApplicationTitle">दूसरा एप्प इस्तमाल करें</string>
|
||||
<string name="importOptionApplicationButton">दूसरा एप्प इस्तमाल करें</string>
|
||||
<string name="about">बारे में</string>
|
||||
<string name="starImage">पसंदीदा स्टार</string>
|
||||
<string name="settings_light_theme">उजालित</string>
|
||||
<string name="settings_dark_theme">अँधेरा</string>
|
||||
<string name="settings">व्यवस्थाएं (सेटिंगें)</string>
|
||||
<string name="settings_system_theme">तंत्र</string>
|
||||
<string name="settings_card_orientation">बारकोड का अनुकूलन(ओरिएंटेशन)</string>
|
||||
<string name="settings_landscape_orientation">आयत रूप(लैंडस्केप)</string>
|
||||
<string name="settings_follow_system_orientation">सिस्टम का पालन करें</string>
|
||||
<string name="settings_portrait_orientation">पोट्रैट</string>
|
||||
<string name="settings_max_font_size_scale">अक्षर का अधिकतम नाप</string>
|
||||
<string name="settings_display_barcode_max_brightness">बारकोड का दृश्य उजालित(ब्राइट) करें</string>
|
||||
<string name="settings_keep_screen_on">स्क्रीन को चालू रखें</string>
|
||||
<string name="cameraPermissionDeniedTitle">हम कैमरा तक पहुँच नहीं सकते</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">बारकोड स्कैन करने के लिए,को आपके कैमरा का इस्तेमाल करना होगा। इजाज़त कि व्यवस्था (सेटिंग) बदलने के लिए यहाँ दबायें।</string>
|
||||
<string name="importOptionApplicationExplanation">फाइल खोलने के लिए कोई भी ऐप या अपना पसंदिता फाइल मैनेजर का इस्तेमाल करे।</string>
|
||||
<string name="settings_category_title_ui">उपयोक्ता अंतरापृष्ठ (यूजर इंटरफ़ेस)</string>
|
||||
<string name="settings_theme">विषय</string>
|
||||
<string name="barcodeType">बारकोड का प्रकार</string>
|
||||
<string name="barcodeNoBarcode">कोई बारकोड नहीं है</string>
|
||||
<string name="noBarcode">बारकोड नहीं है</string>
|
||||
<string name="copy_to_clipboard">पहचान पत्र(आई डी) को क्लिपबोर्ड में कॉपी करें</string>
|
||||
<string name="scanCardBarcode">बारकोड स्कैन करें</string>
|
||||
<string name="cardShortcut">कार्ड का सरल उपाय (शॉर्टकट)</string>
|
||||
<string name="noGiftCards">\"+\" बटन दबाके कार्ड जोड़ें वा मेन्यू से कार्ड आयात करें</string>
|
||||
<string name="importExportHelp">तथ्य (डाटा) को बैकअप करना हमें उसे दूसरे डिवाइस में भेजने देता है|</string>
|
||||
<string name="barcodeImageDescriptionWithType"><xliff:g>%s</xliff:g> का बारकोड</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">स्क्रीन को लॉक होने से रोकें</string>
|
||||
<string name="enterBarcodeInstructions">अपनी आई डी लिखें तथा या तो बारकोड प्रकार चुनें, या फिर कोई बारकोड नहीं है चुनें|</string>
|
||||
<string name="settings_lock_on_opening_orientation">कार्ड खोलते समय प्रयोग करि गयी अवस्था को प्रतिबन्ध करें</string>
|
||||
<string name="intent_import_card_from_url_share_text">मैं तुम्हें एक कार्ड भेजना चाहता हूँ</string>
|
||||
<string name="selectBarcodeTitle">बारकोड चुनें</string>
|
||||
<string name="thumbnailDescription">छोटा चित्र</string>
|
||||
<string name="noGroups">+ दबा कर समूहों को भागीकरण के लिए चुनें|</string>
|
||||
<string name="sameAsCardId">आई डी से निरंतर</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">में तुम्हें कुछ कार्ड्स भेजना चाहता हूँ</string>
|
||||
<string name="importSuccessful">जानकारी प्राप्त हुई</string>
|
||||
<string name="enter_group_name">समूह का नाम लिखें</string>
|
||||
<string name="group_edit">समूह बदलें</string>
|
||||
<string name="noGroupCards">यह समूह खाली है</string>
|
||||
<string name="group_name_already_in_use">समूह का नाम पहले ही प्रयोग में है</string>
|
||||
<string name="group_name_is_empty">समूह का नाम खाली नहीं हो सकता</string>
|
||||
<string name="all">सब</string>
|
||||
<string name="deleteConfirmationGroup">समूह को मिटा दिया जाए\?</string>
|
||||
<string name="moveUp">ऊपर की और बढ़ें</string>
|
||||
<string name="moveDown">नीचे की और बढ़ें</string>
|
||||
<string name="leaveWithoutSaveTitle">निकास करें</string>
|
||||
<string name="addFromImage">गैलरी से चित्र चुनें</string>
|
||||
<string name="card">कार्ड</string>
|
||||
<string name="barcode">बारकोड</string>
|
||||
<string name="editBarcode">बारकोड में बदलाव करें</string>
|
||||
<string name="expiryDate">समाप्ति दिन</string>
|
||||
<string name="never">कभी नहीं</string>
|
||||
<string name="chooseExpiryDate">समाप्ति दिन चुनें</string>
|
||||
<string name="moveBarcodeToTopOfScreen">बार कोड को स्क्रीन के ऊपरी भाग पर लाएं</string>
|
||||
<string name="moveBarcodeToCenterOfScreen">बार कोड को स्क्रीन के बीच में लाएं</string>
|
||||
<string name="noBarcodeFound">कोई बारकोड नहीं पाया गया</string>
|
||||
<string name="errorReadingImage">चित्र को पढ़ना संभव नहीं हुआ</string>
|
||||
<string name="balance">संतुलन</string>
|
||||
<string name="currency">मुद्रा</string>
|
||||
<string name="accept">स्वीकार</string>
|
||||
<string name="exportSuccessful">डेटा निर्यात किया गया</string>
|
||||
<string name="groupsList">समूह: <xliff:g>%s</xliff:g></string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> अंक</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> अंक</item>
|
||||
</plurals>
|
||||
<string name="privacy_policy_popup_text">निजता नीति नोटिस (कुछ ऐप स्टोर के लिए आवश्यक):
|
||||
\n
|
||||
\nकोई भी डेटा एकत्र नहीं किया जाता है, जिसकी पुष्टि कोई भी कर सकता है क्योंकि हमारा ऐप मुफ्त सॉफ्टवेयर है।</string>
|
||||
<string name="importCatimaMessage">आयात करने के लिए, <i>catima.zip</i> फाइल को चुने जो की Catima से निर्यात किया गया था.
|
||||
\nदूसरे Catima ऍप के आयात/निर्यात मेनू से निर्यात बटन दबाकर, पहले catima.zip फाइल को बनाये.</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> चयनित</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> चयनित.</item>
|
||||
</plurals>
|
||||
<string name="groups">समूहों</string>
|
||||
<string name="app_copyright_fmt" tools:ignore="PluralsCandidate">कॉपीराइट © 2019–<xliff:g>%d</xliff:g> Sylvia van Os</string>
|
||||
<plurals name="groupCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> कार्ड</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> कार्डों</item>
|
||||
</plurals>
|
||||
<string name="group_updated">समूह अपडेट किया गया</string>
|
||||
<string name="failedOpeningFileManager">पहले एक फाइल मैनेजर इनस्टॉल करें.</string>
|
||||
<string name="leaveWithoutSaveConfirmation">बिना सुरक्षित किये छोड़े\?</string>
|
||||
<string name="addManually">मैन्युअली आई डी दर्ज करें</string>
|
||||
<string name="editGroup">समूह संपादन: <xliff:g>%s</xliff:g></string>
|
||||
<string name="points">अंक</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> एक वैध शेष राशि नहीं है.</string>
|
||||
<string name="chooseImportType">यहाँ से डेटा का आयात करें</string>
|
||||
<string name="privacy_policy">निजता नीति</string>
|
||||
<string name="importCatima">कैटिमा से आयात करें</string>
|
||||
<string name="app_license">कॉपीलेफ्ट लिबर सॉफ्टवेयर, GPLv3+ लाइसेंस प्राप्त</string>
|
||||
<string name="about_title_fmt"><xliff:g id="app_name">%s</xliff:g> के बारे में</string>
|
||||
<string name="debug_version_fmt">संस्करण: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt"><xliff:g id="app_revision_url">%s</xliff:g> संशोधन के बारे में</string>
|
||||
<string name="copy_to_clipboard_toast">आई डी क्लिपबोर्ड पर कॉपी किया गया</string>
|
||||
</resources>
|
||||
@@ -22,7 +22,7 @@
|
||||
<string name="action_add">Dodaj</string>
|
||||
<string name="storeName">Ime</string>
|
||||
<string name="note">Napomena</string>
|
||||
<string name="noMatchingGiftCards">Ništa nisam našao. Pokušajte promijeniti pretraživanje.</string>
|
||||
<string name="noMatchingGiftCards">Nema rezultata. Pokušajte promijeniti pretraživanje.</string>
|
||||
<string name="cardId">ID kartice</string>
|
||||
<string name="barcodeType">Vrsta crtičnog koda</string>
|
||||
<string name="barcodeNoBarcode">Na ovoj kartici nema crtičnog koda</string>
|
||||
@@ -44,7 +44,6 @@
|
||||
<string name="exportOptionExplanation">Podaci će biti zabilježeni na odabranom mjestu.</string>
|
||||
<string name="exportFailedTitle">Izvoz nije uspio</string>
|
||||
<string name="exporting">Opskrba…</string>
|
||||
<string name="noExternalStoragePermissionError">Najprije odobrite dopuštenje za vanjsku pohranu za uvoz ili izvoz kartica</string>
|
||||
<string name="importOptionFilesystemExplanation">Odaberite određenu datoteku iz datotečnog sustava.</string>
|
||||
<string name="importOptionApplicationTitle">Koristite drugu aplikaciju</string>
|
||||
<string name="settings">Postavke</string>
|
||||
@@ -80,4 +79,5 @@
|
||||
<string name="leaveWithoutSaveTitle">Izlaz</string>
|
||||
<string name="card">Karta</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Otići bez očuvanja\?</string>
|
||||
<string name="noGiftCardsGroup">Izradite neke kartice, a zatim ih dodijelite grupi ovdje.</string>
|
||||
</resources>
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="noGiftCards">Nyomja meg a + jelet a kártya hozzáadásához, vagy importáljon a ⋮ menüvel.</string>
|
||||
<string name="noGiftCards">Kattintson a + plusz gombra egy kártya hozzáadásához, vagy importáljon a ⋮ menüből.</string>
|
||||
<string name="action_add">Hozzáadás</string>
|
||||
<string name="action_search">Keresés</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> kiválasztva</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kiválasztva</item>
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> kiválasztott</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kiválasztottak</item>
|
||||
</plurals>
|
||||
<string name="noCardsMessage">Először adjon hozzá egy kártyát</string>
|
||||
<string name="noGiftCardsGroup">Hozzon létre kártyákat, és rendelje hozzá a megfelelő csoporthoz.</string>
|
||||
@@ -24,8 +24,8 @@
|
||||
<string name="delete">Törlés</string>
|
||||
<string name="confirm">Alkalmaz</string>
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="one"><xliff:g>%d</xliff:g> törlése</item>
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> törlése</item>
|
||||
<item quantity="one">Törölje az <xliff:g>%d</xliff:g> kártyát</item>
|
||||
<item quantity="other">Törölje az <xliff:g>%d</xliff:g> kártyákat</item>
|
||||
</plurals>
|
||||
<string name="deleteConfirmation">Véglegesen törli a kártyát\?</string>
|
||||
<string name="ok">Rendben</string>
|
||||
@@ -81,7 +81,6 @@
|
||||
<string name="exportFailed">Exportálás sikertelen</string>
|
||||
<string name="importing">Importálás…</string>
|
||||
<string name="exporting">Exportálás…</string>
|
||||
<string name="noExternalStoragePermissionError">Külső háttértárhoz való hozzáférés engedélyezése adat import vagy export miatt</string>
|
||||
<string name="exportOptionExplanation">Az adatokat a kiválasztott helyre fogjuk menteni.</string>
|
||||
<string name="importOptionFilesystemTitle">Importálás fájlrendszerből</string>
|
||||
<string name="importOptionFilesystemButton">A fájlrendszerből</string>
|
||||
@@ -137,7 +136,7 @@
|
||||
<string name="currency">Valuta</string>
|
||||
<string name="points">Pontok</string>
|
||||
<string name="parsingBalanceFailed">A <xliff:g>%s</xliff:g> nem tűnik valós egyenlegnek.</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="app_loyalty_card_keychain">Hűségkártya kulcstartó</string>
|
||||
<string name="privacy_policy">Adatvédelmi Szabályzat</string>
|
||||
<string name="accept">Elfogad</string>
|
||||
<string name="importCatima">Importálás Catimából</string>
|
||||
@@ -179,7 +178,7 @@
|
||||
<string name="app_contributors">Lehetővé tette: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="showMoreInfo">Infó mutatása</string>
|
||||
<string name="hideMoreInfo">Infó elrejtése</string>
|
||||
<string name="swipeToSwitchImages">Húzza oldalra vagy tartsa nyomva a kép megváltoztatásáért</string>
|
||||
<string name="swipeToSwitchImages">Csúsztassa ujját a képek váltásához, tartsa lenyomva a kép megnyitásához a Galéria alkalmazásban</string>
|
||||
<string name="sort_by_balance">Egyenleg</string>
|
||||
<string name="reverse">...fordított sorrendben</string>
|
||||
<string name="sort_by">Rendezés mint</string>
|
||||
@@ -200,7 +199,7 @@
|
||||
</plurals>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="one"><xliff:g>%s</xliff:g> pont</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> pont</item>
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> pontok</item>
|
||||
</plurals>
|
||||
<string name="chooseImportType">Adat importálása innen</string>
|
||||
<string name="thumbnailDescription">Előkép</string>
|
||||
@@ -226,4 +225,41 @@
|
||||
\nSEMMILYEN ADATGYŰJTÉS NINCS, amit bárki ellenőrizhet, lévén hogy az app gáttalan szoftver.</string>
|
||||
<string name="importFidmeMessage">Válassza ki a <i>fidme-export-request-xxxxxx.zip</i> nevű FidMe exportot, majd importálja be és válassza a manuális vonalkód opciót utána.
|
||||
\nEzt a FidMe-ben megtalálja a profiljában az Adat Védelem résznél ha rányom az Adataim Kivonata linkre.</string>
|
||||
<string name="settings_card_orientation">Vonalkód tájolás</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="one"><xliff:g>%1$d</xliff:g> kártya (<xliff:g id="archivedCount">%2$d</xliff:g> archiválva)</item>
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> kártyák (<xliff:g id="archivedCount">%2$d</xliff:g> archiválva)</item>
|
||||
</plurals>
|
||||
<string name="noUnarchivedCardsMessage">Nincs archiválatlan kártya</string>
|
||||
<string name="failedToOpenUrl">Először telepíts egy webböngészőt</string>
|
||||
<string name="failedLaunchingPhotoPicker">Nem található támogatott képnézegető app</string>
|
||||
<string name="previousCard">Előző</string>
|
||||
<string name="nextCard">Következő</string>
|
||||
<string name="settings_portrait_orientation">Álló</string>
|
||||
<string name="settings_follow_system_orientation">Rendszer követése</string>
|
||||
<string name="settings_lock_on_opening_orientation">A használt tájolás zárolása kártya használatakor</string>
|
||||
<string name="settings_landscape_orientation">Fekvő</string>
|
||||
<string name="settings_oled_dark">Tiszta fekete háttér sötét témánál</string>
|
||||
<string name="include_if_asking_support">Ha támogatást szeretnél igénybe venni, oszd meg az alábbi információkat:</string>
|
||||
<string name="archive">Archivál</string>
|
||||
<string name="unarchive">Archiválás megszüntetése</string>
|
||||
<string name="archived">Kártya archiválása</string>
|
||||
<string name="archiveList">Archivál</string>
|
||||
<string name="duplicateCard">Másolat</string>
|
||||
<string name="currentBalanceSentence">Jelenlegi egyenleg: <xliff:g>%s</xliff:g></string>
|
||||
<string name="updateBalanceHint">Adja meg az összeget</string>
|
||||
<string name="importCards">Kártyák importálása</string>
|
||||
<string name="updateBalanceTitle">Mennyit költöttél\?</string>
|
||||
<string name="newBalanceSentence">Új egyenleg: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">Nem sikerült hozzáférni a kamerához</string>
|
||||
<string name="failedToRetrieveImageFile">Nem sikerült lekérni a képfájlt</string>
|
||||
<string name="barcodeLongPressMessage">Csak képek nyithatók meg a galéria alkalmazásban</string>
|
||||
<string name="unarchived">Archiválatlan kártya</string>
|
||||
<string name="welcome">Üdvözöljük Catimában</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="one">Archívum megtekintése (<xliff:g>%1$d</xliff:g> kártya)</item>
|
||||
<item quantity="other">Archívum megtekintése (<xliff:g>%1$d</xliff:g> kártyák)</item>
|
||||
</plurals>
|
||||
<string name="updateBalance">Egyenleg frissítése</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">A vonalkódok beolvasásához a Catimának hozzá kell férnie a kamerához. Koppintson ide az engedélybeállítások módosításához.</string>
|
||||
</resources>
|
||||
@@ -7,8 +7,8 @@
|
||||
<string name="edit">Ubah</string>
|
||||
<string name="save">Simpan</string>
|
||||
<string name="deleteTitle">Hapus kartu</string>
|
||||
<string name="cardId">Kartu ID</string>
|
||||
<string name="barcodeType">Tipe barcode</string>
|
||||
<string name="cardId">ID Kartu</string>
|
||||
<string name="barcodeType">Jenis barcode</string>
|
||||
<string name="star">Tambahkan ke favorit</string>
|
||||
<string name="unstar">Hapus dari favorit</string>
|
||||
<string name="action_add">Tambah</string>
|
||||
@@ -16,7 +16,7 @@
|
||||
<string name="sort_by_name">Nama</string>
|
||||
<string name="sort_by_balance">Saldo</string>
|
||||
<string name="sort_by">Sortir dengan</string>
|
||||
<string name="sort">Sortir</string>
|
||||
<string name="sort">Urut</string>
|
||||
<string name="credits">Kredit</string>
|
||||
<string name="license">Lisensi</string>
|
||||
<string name="settings">Pengaturan</string>
|
||||
@@ -27,27 +27,27 @@
|
||||
<string name="share">Bagikan</string>
|
||||
<string name="editCardTitle">Ubah Kartu</string>
|
||||
<string name="addCardTitle">Tambah Kartu</string>
|
||||
<string name="scanCardBarcode">Pindai Kartu Barcode</string>
|
||||
<string name="barcodeNoBarcode">Kartu ini tidak memiliki barcode</string>
|
||||
<string name="scanCardBarcode">Pindai Barcode</string>
|
||||
<string name="barcodeNoBarcode">Tidak ada barcode</string>
|
||||
<string name="cancel">Batalkan</string>
|
||||
<string name="importExport">Import/Ekspor</string>
|
||||
<string name="importExport">Impor/Ekspor</string>
|
||||
<string name="settings_category_title_ui">Tampilan Pengguna</string>
|
||||
<string name="settings_theme">Tema</string>
|
||||
<string name="all">Semua</string>
|
||||
<string name="leaveWithoutSaveTitle">Keluar</string>
|
||||
<string name="card">Kartu</string>
|
||||
<string name="barcode">Barcode</string>
|
||||
<string name="barcode">barcode</string>
|
||||
<string name="chooseExpiryDate">Pilih masa berlaku</string>
|
||||
<string name="noBarcodeFound">Barcode tidak ditemukan</string>
|
||||
<string name="errorReadingImage">TIdak dapat membaca gambar</string>
|
||||
<string name="errorReadingImage">Tidak dapat membaca gambar</string>
|
||||
<string name="balance">Saldo</string>
|
||||
<string name="currency">Mata uang</string>
|
||||
<string name="chooseImportType">Impor data dari?</string>
|
||||
<string name="chooseImportType">Impor data dari</string>
|
||||
<string name="accept">Terima</string>
|
||||
<string name="importCatima">Impor dari Catima</string>
|
||||
<string name="importFidme">Impor dari FidMe</string>
|
||||
<string name="barcodeId">Nilai barcode</string>
|
||||
<string name="sameAsCardId">Sama denga kartu ID</string>
|
||||
<string name="sameAsCardId">Sama dengan ID</string>
|
||||
<string name="setBarcodeId">Tentukan nilai barcode</string>
|
||||
<string name="photos">Foto</string>
|
||||
<string name="setFrontImage">Atur gambar bagian depan</string>
|
||||
@@ -75,32 +75,31 @@
|
||||
<string name="takePhoto">Ambil foto</string>
|
||||
<string name="removeImage">Hapus gambar</string>
|
||||
<string name="setBackImage">Atur gambar bagian belakang</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Saya ingin berbagi kartu dengan anda</string>
|
||||
<string name="noGiftCards">Klik tanda + tombol tambah untuk menambahkan kartu, atau mengimpor beberapa kartu melalui menu ⋮ terlebih dahulu.</string>
|
||||
<string name="noMatchingGiftCards">Tidak menemukan apapun. Coba untuk mengubah pencarian anda.</string>
|
||||
<string name="intent_import_card_from_url_share_multiple_text">Saya ingin berbagi kartu dengan Anda</string>
|
||||
<string name="noGiftCards">Tap tanda tombol plus ( + ) untuk menambahkan kartu, atau mengimpor nya melalui menu ( ⋮ ).</string>
|
||||
<string name="noMatchingGiftCards">Tidak menemukan apapun. Cobalah untuk mengubah pencarian anda.</string>
|
||||
<string name="noBarcode">Bukan barcode</string>
|
||||
<string name="confirm">Konfirmasi</string>
|
||||
<string name="copy_to_clipboard">Salin ID</string>
|
||||
<string name="copy_to_clipboard">Salin ID ke papan klip</string>
|
||||
<string name="sendLabel">Kirim…</string>
|
||||
<string name="noCardsMessage">Tambah kartu terlebih dahulu</string>
|
||||
<string name="noStoreError">Nama masih kosong</string>
|
||||
<string name="noCardIdError">Kartu ID masih kosong</string>
|
||||
<string name="noCardIdError">Tidak ada ID yang dimasukkan</string>
|
||||
<string name="noCardExistsError">Tidak dapat menemukan kartu</string>
|
||||
<string name="failedParsingImportUriError">Tidak dapat menguraikan alamat impor situs web</string>
|
||||
<string name="failedParsingImportUriError">Tidak dapat memparsing impor URI</string>
|
||||
<string name="exportName">Ekspor</string>
|
||||
<string name="importSuccessfulTitle">Sudah diimpor</string>
|
||||
<string name="importFailedTitle">Impor gagal</string>
|
||||
<string name="importFailed">Tidak dapat mengimpor kartu</string>
|
||||
<string name="importFailed">Tidak dapat mengimpor</string>
|
||||
<string name="exportSuccessfulTitle">Sudah diekspor</string>
|
||||
<string name="exportFailedTitle">Ekspor gagal</string>
|
||||
<string name="exportFailed">Tidak dapat mengekspor kartu</string>
|
||||
<string name="importing">Mengimpor…</string>
|
||||
<string name="exporting">Mengekspor…</string>
|
||||
<string name="noExternalStoragePermissionError">Berikan izin penyimpanan eksternal untuk mengimpor atau mengekspor kartu terlebih dahulu</string>
|
||||
<string name="exportFailed">Tidak dapat mengekspor</string>
|
||||
<string name="importing">Sedang mengimpor…</string>
|
||||
<string name="exporting">Sedang mengekspor…</string>
|
||||
<string name="exportOptionExplanation">Data akan ditulis ke lokasi pilihan Anda.</string>
|
||||
<string name="importOptionFilesystemTitle">Impor dari sistem</string>
|
||||
<string name="importOptionFilesystemExplanation">Pilih file dari sistem.</string>
|
||||
<string name="importOptionFilesystemButton">Dari sistem</string>
|
||||
<string name="importOptionFilesystemTitle">Impor dari pengelola file bawaan</string>
|
||||
<string name="importOptionFilesystemExplanation">Pilih file dari pengelola file bawaan.</string>
|
||||
<string name="importOptionFilesystemButton">Dari pengelola file bawaan</string>
|
||||
<string name="importOptionApplicationTitle">Gunakan aplikasi lain</string>
|
||||
<string name="importOptionApplicationExplanation">Gunakan aplikasi lain atau pengelola file favorit anda untuk membuka file.</string>
|
||||
<string name="importOptionApplicationButton">Gunakan aplikasi lain</string>
|
||||
@@ -114,29 +113,29 @@
|
||||
<string name="app_revision_fmt">Info Revisi: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries">Pustaka pihak ketiga gratis: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources">Sumber daya pihak ketiga gratis: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="enterBarcodeInstructions">Masukkan ID kartu, dan pilih jenis barcodenya di bawah atau \"Kartu ini tidak memiliki barcode\".</string>
|
||||
<string name="copy_to_clipboard_toast">ID kartu telah disalin</string>
|
||||
<string name="thumbnailDescription">Gambar tampilan untuk kartu</string>
|
||||
<string name="enterBarcodeInstructions">Masukkan ID, dan pilih jenis barcode di bawah ini, atau \"Tidak ada barcode\".</string>
|
||||
<string name="copy_to_clipboard_toast">ID disalin ke papan klip</string>
|
||||
<string name="thumbnailDescription">Gambar tampilan</string>
|
||||
<string name="starImage">Favorit</string>
|
||||
<string name="settings_light_theme">Terang</string>
|
||||
<string name="settings_dark_theme">Gelap</string>
|
||||
<string name="settings_max_font_size_scale">Ukuran maksimal huruf</string>
|
||||
<string name="settings_display_barcode_max_brightness">Terangkan tampilan barcode</string>
|
||||
<string name="settings_keep_screen_on">Biarkan layar menyala</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Mencegah layar menyala</string>
|
||||
<string name="settings_disable_lockscreen_while_viewing_card">Cegah kunci layar</string>
|
||||
<string name="intent_import_card_from_url_share_text">Saya ingin berbagi kartu dengan anda</string>
|
||||
<string name="importSuccessful">Data kartu terimpor</string>
|
||||
<string name="exportSuccessful">Data kartu terekspor</string>
|
||||
<string name="importSuccessful">Data terimpor</string>
|
||||
<string name="exportSuccessful">Data terekspor</string>
|
||||
<string name="enter_group_name">Masukan nama grup</string>
|
||||
<string name="groups">Grup</string>
|
||||
<string name="noGroups">Klik pada tombol tambah + untuk menambahkan grup atau kategori terlebih dahulu.</string>
|
||||
<string name="noGroupCards">Grup ini tidak memilik kartu</string>
|
||||
<string name="noGroups">Klik pada tombol tambah + untuk menambahkan grup untuk pengkategorian.</string>
|
||||
<string name="noGroupCards">Grup ini kosong</string>
|
||||
<string name="deleteConfirmationGroup">Hapus grup?</string>
|
||||
<string name="failedOpeningFileManager">Instal aplikasi pengelola file terlebih dahulu.</string>
|
||||
<string name="failedOpeningFileManager">Pasang aplikasi pengelola berkas terlebih dahulu.</string>
|
||||
<string name="moveUp">Pindah ke atas</string>
|
||||
<string name="moveDown">Pindah ke bawah</string>
|
||||
<string name="leaveWithoutSaveConfirmation">Keluar tanpa menyimpan?</string>
|
||||
<string name="addManually">Masukan ID kartu</string>
|
||||
<string name="addManually">Masukan ID</string>
|
||||
<string name="addFromImage">Pilih gambar dari galeri</string>
|
||||
<string name="groupsList">Grup: <xliff:g>%s</xliff:g></string>
|
||||
<string name="expiryStateSentence">Masa ber: <xliff:g>%s</xliff:g></string>
|
||||
@@ -149,7 +148,7 @@
|
||||
<string name="moveBarcodeToCenterOfScreen">Pusatkan barcode pada layar</string>
|
||||
<string name="points">Poin</string>
|
||||
<string name="parsingBalanceFailed"><xliff:g>%s</xliff:g> sepertinya bukan saldo yang valid.</string>
|
||||
<string name="app_loyalty_card_keychain">Loyalty Card Keychain</string>
|
||||
<string name="app_loyalty_card_keychain">Gantungan kunci kartu kesetiaan</string>
|
||||
<string name="privacy_policy">Kebijakan Privasi</string>
|
||||
<string name="privacy_policy_popup_text">Pemberitahuan kebijakan privasi (diperlukan oleh beberapa toko aplikasi):
|
||||
\n
|
||||
@@ -169,27 +168,27 @@
|
||||
\nBuat dengan menekan Ekspor di Vault Voucher terlebih dahulu.</string>
|
||||
<string name="unsupportedBarcodeType">Jenis barcode ini belum dapat ditampilkan. Ini mungkin didukung di versi aplikasi yang lebih baru.</string>
|
||||
<string name="wrongValueForBarcodeType">Nilai tidak berlaku untuk jenis barcode yang dipilih</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID kartu telah disalin</string>
|
||||
<string name="frontImageDescription">Gambar depan kartu</string>
|
||||
<string name="backImageDescription">Gambar belakang kartu</string>
|
||||
<string name="copy_to_clipboard_multiple_toast">ID disalin ke papan klip</string>
|
||||
<string name="frontImageDescription">Gambar depan</string>
|
||||
<string name="backImageDescription">Gambar belakang</string>
|
||||
<string name="updateBarcodeQuestionTitle">Perbarui barcode?</string>
|
||||
<string name="updateBarcodeQuestionText">Anda mengubah ID kartu. Apakah Anda juga ingin memperbarui barcode untuk menggunakan nilai yang sama?</string>
|
||||
<string name="updateBarcodeQuestionText">Anda mengubah ID. Apakah Anda juga ingin memperbarui barcode untuk menggunakan nilai yang sama\?</string>
|
||||
<string name="passwordRequired">Silahkan masukan kata sandi</string>
|
||||
<string name="exportPassword">Tetapkan kata sandi untuk melindungi ekspor anda (opsional)</string>
|
||||
<string name="failedGeneratingShareURL">Tidak dapat membuat alamat berbagi. Mohon laporkan ini.</string>
|
||||
<string name="app_contributors">Pengembangan dibantu oleh: <xliff:g id="app_contributors">%s</xliff:g></string>
|
||||
<string name="swipeToSwitchImages">Geser atau tekan yang lama untuk mengganti gambar</string>
|
||||
<string name="reverse">Ubah urutan</string>
|
||||
<string name="swipeToSwitchImages">Geser untuk beralih gambar, tahan untuk membuka gambar di aplikasi galeri</string>
|
||||
<string name="reverse">…dalam urutan terbalik</string>
|
||||
<string name="version_history">Riwayat Versi</string>
|
||||
<string name="help_translate_this_app">Bantu terjemahkan aplikasi ini</string>
|
||||
<string name="source_repository">Sumber Repositori</string>
|
||||
<string name="on_github">di GitHub</string>
|
||||
<string name="and_data_usage">dan penggunaan data</string>
|
||||
<string name="on_google_play">di Google Play</string>
|
||||
<string name="cardShortcut">Pintasan kartu</string>
|
||||
<string name="card_ids_copied">ID kartu yang tersalin</string>
|
||||
<string name="barcodeImageDescriptionWithType">Gambar dari jenis barcode <xliff:g>%s</xliff:g></string>
|
||||
<string name="importExportHelp">Mencadangkan kartu memungkinkan anda memindahkannya ke perangkat lain.</string>
|
||||
<string name="cardShortcut">Pintasan Kartu</string>
|
||||
<string name="card_ids_copied">ID(s) yang disalin</string>
|
||||
<string name="barcodeImageDescriptionWithType">Gambar <xliff:g>%s</xliff:g> barcode</string>
|
||||
<string name="importExportHelp">Mencadangkan data anda akan memungkinkan memindahkannya ke perangkat lain.</string>
|
||||
<plurals name="selectedCardCount">
|
||||
<item quantity="other"><xliff:g>%d</xliff:g> kartu dipilih</item>
|
||||
</plurals>
|
||||
@@ -202,4 +201,66 @@
|
||||
<plurals name="deleteCardsTitle">
|
||||
<item quantity="other">Hapus <xliff:g>%d</xliff:g> kartu</item>
|
||||
</plurals>
|
||||
<string name="editGroup">Menyunting Grup: <xliff:g>%s</xliff:g></string>
|
||||
<string name="selectColor">Pilih warna</string>
|
||||
<string name="noGiftCardsGroup">Buat beberapa kartu, kemudian masukkan mereka ke grup di sini.</string>
|
||||
<string name="group_name_already_in_use">Nama grup telah dipakai</string>
|
||||
<string name="setIcon">Atur ikon</string>
|
||||
<string name="settings_oled_dark">Latar belakang gelap gulita untuk tema gelap</string>
|
||||
<string name="group_edit">Sunting Grup</string>
|
||||
<string name="group_name_is_empty">Nama grup tidak boleh kosong</string>
|
||||
<string name="group_updated">Grup diperbarui</string>
|
||||
<plurals name="groupCardCountWithArchived">
|
||||
<item quantity="other"><xliff:g>%1$d</xliff:g> kartu (<xliff:g id="archivedCount">%2$d</xliff:g> diarsipkan)</item>
|
||||
</plurals>
|
||||
<string name="translate_platform">di Weblate</string>
|
||||
<string name="action_show_details">Tampilkan detail</string>
|
||||
<string name="action_hide_details">Sembunyikan detail</string>
|
||||
<string name="welcome">Selamat datang di Catima</string>
|
||||
<string name="failedToOpenUrl">Install browser web terlebih dahulu</string>
|
||||
<plurals name="viewArchivedCardsWithCount">
|
||||
<item quantity="other">Lihat arsip (<xliff:g>%1$d</xliff:g> kartu)</item>
|
||||
</plurals>
|
||||
<string name="failedLaunchingPhotoPicker">Tidak dapat menemukan aplikasi galeri yang didukung</string>
|
||||
<string name="previousCard">Sebelumnya</string>
|
||||
<string name="nextCard">Berikutnya</string>
|
||||
<string name="settings_card_orientation">Orientasi Barcode</string>
|
||||
<string name="settings_follow_system_orientation">Ikuti sistem</string>
|
||||
<string name="settings_portrait_orientation">Potret</string>
|
||||
<string name="settings_landscape_orientation">Lanskap</string>
|
||||
<string name="settings_lock_on_opening_orientation">Kunci ke orientasi yang digunakan saat membuka kartu</string>
|
||||
<plurals name="balancePoints">
|
||||
<item quantity="other"><xliff:g>%s</xliff:g> poin</item>
|
||||
</plurals>
|
||||
<string name="showMoreInfo">Tampilkan informasi</string>
|
||||
<string name="hideMoreInfo">Sembunyikan informasi</string>
|
||||
<string name="shortcutSelectCard">Pilih kartu</string>
|
||||
<string name="set_scale">Atur skala</string>
|
||||
<string name="include_if_asking_support">Jika anda ingin meminta bantuan, sertakan informasi berikut:</string>
|
||||
<string name="duplicateCard">Duplikat</string>
|
||||
<string name="archive">Arsip</string>
|
||||
<string name="archived">Kartu diarsipkan</string>
|
||||
<string name="archiveList">Arsip</string>
|
||||
<string name="failedToRetrieveImageFile">Gagal mengambil file gambar</string>
|
||||
<string name="barcodeLongPressMessage">Hanya gambar yang dapat dibuka di aplikasi galeri</string>
|
||||
<string name="unarchive">Ekstrak</string>
|
||||
<string name="unarchived">Kartu tidak diarsipkan</string>
|
||||
<string name="noUnarchivedCardsMessage">Tidak ada kartu yang diekstrak</string>
|
||||
<string name="options">Opsi</string>
|
||||
<string name="starred">Berbintang</string>
|
||||
<string name="importCards">Import kartu</string>
|
||||
<string name="newBalanceSentence">Saldo baru: <xliff:g>%s</xliff:g></string>
|
||||
<string name="cameraPermissionDeniedTitle">Tidak dapat mengakses kamera</string>
|
||||
<string name="updateBalance">Perbarui saldo</string>
|
||||
<string name="updateBalanceHint">Masukkan jumlah</string>
|
||||
<string name="currentBalanceSentence">Saldo saat ini: <xliff:g>%s</xliff:g></string>
|
||||
<string name="updateBalanceTitle">Berapa banyak yang telah kamu habiskan \?</string>
|
||||
<string name="noCameraPermissionDirectToSystemSetting">Untuk memindai barcode, Catima membutuhkan akses ke kamera mu. Tap disini untuk mengganti pengaturan perizinan mu.</string>
|
||||
<string name="cameraPermissionRequired">Berikan izin untuk mengakses kamera anda…</string>
|
||||
<string name="storageReadPermissionRequired">Berikan izin untuk membaca penyimpanan anda…</string>
|
||||
<string name="validFromDate">Valid dari</string>
|
||||
<string name="validFromSentence">Valid dari:
|
||||
\n<xliff:g>%s</xliff:g></string>
|
||||
<string name="anyDate">Kapan pun</string>
|
||||
<string name="chooseValidFromDate">Pilih valid dari tanggal</string>
|
||||
</resources>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user