Skip to content

Commit 9b1c372

Browse files
committed
feat: Major release v2.2.2
- Added support for adding contact photos - Caller ID popup now appears on lock screen - Minor bug fixes and stability improvements
1 parent 0eac924 commit 9b1c372

32 files changed

+808
-155
lines changed

.github/workflows/android-release.yml

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ jobs:
2525
node-version: ${{ env.NODE_VERSION }}
2626
cache: "npm"
2727

28+
- name: Cache node modules
29+
uses: actions/cache@v4
30+
with:
31+
path: ~/.npm
32+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
33+
restore-keys: |
34+
${{ runner.os }}-node-
35+
2836
- name: Setup Java JDK
2937
uses: actions/setup-java@v4
3038
with:
@@ -36,10 +44,33 @@ jobs:
3644

3745
- name: Setup Gradle
3846
uses: gradle/gradle-build-action@v2
47+
with:
48+
cache-read-only: false
49+
50+
- name: Cache Gradle dependencies
51+
uses: actions/cache@v4
52+
with:
53+
path: |
54+
~/.gradle/caches
55+
~/.gradle/wrapper
56+
android/.gradle
57+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
58+
restore-keys: |
59+
${{ runner.os }}-gradle-
3960
4061
- name: Make gradlew executable
4162
run: chmod +x android/gradlew
4263

64+
- name: Cache Android build artifacts
65+
uses: actions/cache@v4
66+
with:
67+
path: |
68+
android/app/build
69+
android/build
70+
key: ${{ runner.os }}-android-build-${{ github.sha }}
71+
restore-keys: |
72+
${{ runner.os }}-android-build-
73+
4374
- name: Decode Keystore
4475
env:
4576
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
@@ -79,11 +110,9 @@ jobs:
79110
80111
## ✨ What's New in ${{ steps.tag.outputs.tag }}
81112
82-
- **Long Press to Copy Contact Info:**
83-
You can now long press on a contact to quickly copy their information.
84-
85-
- **Bug Fixes:**
86-
Minor bug fixes and stability improvements.
113+
- Added support for adding contact photos
114+
- Caller ID popup now appears on lock screen
115+
- Minor bug fixes and stability improvements
87116
88117
## 📦 Download Options
89118

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ When you receive calls from unknown numbers but don't want to save them to your
7171
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png" width="170">](https://apt.izzysoft.de/packages/com.lulu786.Alternate)
7272
[<img src="get-it-on-github.png" width="170">](https://github.com/BioHazard786/Alternate/releases)
7373
[<img src="https://www.openapk.net/images/openapk-badge.png" width="170">](https://www.openapk.net/alternate/com.lulu786.Alternate/)
74+
[<img src="get-it-on-obtainium.png" width="170">](https://apps.obtainium.imranr.dev/redirect?r=obtainium://add/https://github.com/BioHazard786/Alternate/)
7475

7576
## Installation
7677

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ android {
101101
applicationId 'com.lulu786.Alternate'
102102
minSdkVersion rootProject.ext.minSdkVersion
103103
targetSdkVersion rootProject.ext.targetSdkVersion
104-
versionCode 7
105-
versionName "2.1.2"
104+
versionCode 8
105+
versionName "2.2.2"
106106
}
107107

108108
signingConfigs {

android/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
xmlns:tools="http://schemas.android.com/tools">
33

44
<!-- Explicitly remove permissions added by expo-file-system -->
5-
<uses-permission android:name="android.permission.INTERNET" tools:node="remove" />
5+
<!-- <uses-permission android:name="android.permission.INTERNET" tools:node="remove" /> -->
66
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />
77
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" /> -->
88

app.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"expo": {
33
"name": "Alternate",
44
"slug": "Alternate",
5-
"version": "2.1.2",
5+
"version": "2.2.2",
66
"orientation": "portrait",
77
"scheme": "alternate",
88
"userInterfaceStyle": "automatic",
@@ -17,6 +17,7 @@
1717
}
1818
},
1919
"android": {
20+
"versionCode": 8,
2021
"adaptiveIcon": {
2122
"foregroundImage": "./assets/icon/adaptive-icon.png",
2223
"monochromeImage": "./assets/icon/adaptive-icon.png",
@@ -33,6 +34,13 @@
3334
},
3435
"plugins": [
3536
"expo-router",
37+
[
38+
"expo-image-picker",
39+
{
40+
"photosPermission": "The app accesses your photos to let you select contact profile pictures.",
41+
"cameraPermission": "The app accesses your camera to let you take contact profile pictures."
42+
}
43+
],
3644
[
3745
"expo-splash-screen",
3846
{

app/edit-contact.tsx

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Material3Avatar from "@/components/material3-avatar";
21
import PhoneNumberInput from "@/components/phone-number-input";
2+
import PhotoPicker from "@/components/photo-picker";
33
import { additionalFields } from "@/constants/AdditionalFields";
44
import { getAvatarColor } from "@/lib/avatar-utils";
55
import { getCountryByCode } from "@/lib/countries";
@@ -67,6 +67,8 @@ export default function EditContactScreen() {
6767
handleSubmit,
6868
formState: { errors, isSubmitting, isValid },
6969
reset,
70+
setValue,
71+
watch,
7072
} = useForm<ContactFormData>({
7173
defaultValues: {
7274
name: contact?.name || "",
@@ -88,12 +90,15 @@ export default function EditContactScreen() {
8890
birthday: contact?.birthday || "",
8991
labels: contact?.labels || "",
9092
nickname: contact?.nickname || "",
93+
photo: contact?.photo || "",
9194
},
9295
mode: "onChange",
9396
});
9497

9598
const onDismissSnackBar = () => setVisible(false);
9699

100+
const photoUri = watch("photo");
101+
97102
const removeFieldAndReset = (fieldKey: string) => {
98103
const newVisibleFields = new Set(visibleFields);
99104
newVisibleFields.delete(fieldKey);
@@ -215,6 +220,7 @@ export default function EditContactScreen() {
215220
birthday: data.birthday || "",
216221
labels: data.labels?.trim() || "",
217222
nickname: data.nickname?.trim() || "",
223+
photo: data.photo || "",
218224
});
219225

220226
if (success) {
@@ -238,20 +244,19 @@ export default function EditContactScreen() {
238244
return (
239245
<KeyboardAvoidingView
240246
behavior={Platform.OS === "ios" ? "padding" : "height"}
241-
style={[styles.container, { paddingBottom: insets.bottom }]}
247+
style={styles.container}
242248
>
243249
<ScrollView
244250
contentContainerStyle={[
245251
styles.scrollContent,
246-
{ paddingBottom: insets.bottom },
252+
{ paddingBottom: insets.bottom + 16 },
247253
]}
248254
>
249255
<View style={styles.formContainer}>
250-
<Material3Avatar
251-
letter={letter}
252-
backgroundColor={avatarBackgroundColor}
253-
textColor={avatarTextColor}
254-
style={{ marginVertical: 20, alignSelf: "center" }}
256+
<PhotoPicker
257+
photo={photoUri}
258+
onPhotoChange={(uri) => setValue("photo", uri)}
259+
disabled={isSubmitting}
255260
/>
256261
<View>
257262
<Controller
@@ -347,6 +352,7 @@ export default function EditContactScreen() {
347352
}
348353
style={styles.addFieldButton}
349354
labelStyle={{ fontSize: 16 }}
355+
contentStyle={{ marginVertical: 5 }}
350356
disabled={
351357
isSubmitting || visibleFields.size >= additionalFields.length
352358
}
@@ -360,6 +366,7 @@ export default function EditContactScreen() {
360366
disabled={!isValid || isSubmitting}
361367
style={styles.saveButton}
362368
labelStyle={{ fontSize: 16 }}
369+
contentStyle={{ marginVertical: 5 }}
363370
>
364371
Save Changes
365372
</Button>
@@ -405,31 +412,8 @@ const styles = StyleSheet.create({
405412
},
406413
addFieldButton: {
407414
borderRadius: 50,
408-
paddingVertical: 5,
409415
},
410416
saveButton: {
411-
paddingVertical: 5,
412417
borderRadius: 50,
413418
},
414-
bottomSheetContent: {
415-
flex: 1,
416-
paddingVertical: 16,
417-
},
418-
bottomSheetBackground: {
419-
borderTopLeftRadius: 20,
420-
borderTopRightRadius: 20,
421-
},
422-
header: {
423-
flexDirection: "row",
424-
justifyContent: "space-between",
425-
alignItems: "center",
426-
paddingVertical: 16,
427-
paddingHorizontal: 24,
428-
},
429-
title: {
430-
fontWeight: "600",
431-
},
432-
list: {
433-
paddingHorizontal: 16,
434-
},
435419
});

app/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ export default function ContactsScreen() {
232232
onPress: () => router.push("/search"),
233233
},
234234
{
235-
icon: "cog",
235+
icon: "cog-outline",
236236
onPress: () => router.push("/settings"),
237237
},
238238
]}

app/new-contact.tsx

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import PhoneNumberInput from "@/components/phone-number-input";
2+
import PhotoPicker from "@/components/photo-picker";
23
import { additionalFields } from "@/constants/AdditionalFields";
34
import { getCountryByCode } from "@/lib/countries";
45
import { ContactFormData } from "@/lib/types";
@@ -51,6 +52,8 @@ export default function NewContactScreen() {
5152
formState: { errors, isSubmitting, isValid },
5253
setError,
5354
reset,
55+
setValue,
56+
watch,
5457
} = useForm<ContactFormData>({
5558
defaultValues: {
5659
name: "",
@@ -69,12 +72,15 @@ export default function NewContactScreen() {
6972
birthday: "",
7073
labels: "",
7174
nickname: "",
75+
photo: undefined,
7276
},
7377
mode: "onChange", // Validate on change for better UX
7478
});
7579

7680
const onDismissSnackBar = () => setVisible(false);
7781

82+
const photoUri = watch("photo");
83+
7884
const removeFieldAndReset = (fieldKey: string) => {
7985
const newVisibleFields = new Set(visibleFields);
8086
newVisibleFields.delete(fieldKey);
@@ -205,6 +211,7 @@ export default function NewContactScreen() {
205211
birthday: data.birthday || "",
206212
labels: data.labels?.trim() || "",
207213
nickname: data.nickname?.trim() || "",
214+
photo: data.photo || "",
208215
});
209216

210217
if (success) {
@@ -218,15 +225,20 @@ export default function NewContactScreen() {
218225
return (
219226
<KeyboardAvoidingView
220227
behavior={Platform.OS === "ios" ? "padding" : "height"}
221-
style={[styles.container, { paddingBottom: insets.bottom }]}
228+
style={styles.container}
222229
>
223230
<ScrollView
224231
contentContainerStyle={[
225232
styles.scrollContent,
226-
{ paddingBottom: insets.bottom },
233+
{ paddingBottom: insets.bottom + 16 },
227234
]}
228235
>
229236
<View style={styles.formContainer}>
237+
<PhotoPicker
238+
photo={photoUri}
239+
onPhotoChange={(uri) => setValue("photo", uri)}
240+
disabled={isSubmitting}
241+
/>
230242
<View>
231243
<Controller
232244
control={control}
@@ -316,6 +328,7 @@ export default function NewContactScreen() {
316328
}
317329
style={styles.addFieldButton}
318330
labelStyle={{ fontSize: 16 }}
331+
contentStyle={{ marginVertical: 5 }}
319332
disabled={
320333
isSubmitting || visibleFields.size >= additionalFields.length
321334
}
@@ -327,6 +340,7 @@ export default function NewContactScreen() {
327340
onPress={handleSubmit(onSubmit)}
328341
style={styles.saveButton}
329342
labelStyle={{ fontSize: 16 }}
343+
contentStyle={{ marginVertical: 5 }}
330344
disabled={!isValid || isSubmitting}
331345
loading={isSubmitting}
332346
>
@@ -361,55 +375,20 @@ const styles = StyleSheet.create({
361375
},
362376
formContainer: {
363377
flex: 1,
364-
padding: 16,
378+
paddingHorizontal: 16,
365379
gap: 16,
366380
},
367381
list: {
368382
paddingHorizontal: 16,
369383
},
370384
addFieldButton: {
371385
borderRadius: 50,
372-
paddingVertical: 5,
373386
},
374387
saveButton: {
375-
paddingVertical: 5,
376388
borderRadius: 50,
377389
},
378390
buttonContainer: {
379391
marginTop: 20,
380392
gap: 12,
381393
},
382-
bottomSheetContent: {
383-
flex: 1,
384-
paddingVertical: 16,
385-
},
386-
bottomSheetBackground: {
387-
borderTopLeftRadius: 20,
388-
borderTopRightRadius: 20,
389-
},
390-
header: {
391-
flexDirection: "row",
392-
justifyContent: "space-between",
393-
alignItems: "center",
394-
paddingVertical: 16,
395-
paddingHorizontal: 24,
396-
},
397-
title: {
398-
fontWeight: "600",
399-
},
400-
datePickerContainer: {
401-
flex: 1,
402-
paddingHorizontal: 24,
403-
paddingVertical: 16,
404-
},
405-
datePickerButtons: {
406-
flexDirection: "row",
407-
justifyContent: "space-around",
408-
paddingTop: 20,
409-
gap: 16,
410-
},
411-
dateButton: {
412-
flex: 1,
413-
borderRadius: 25,
414-
},
415394
});

0 commit comments

Comments
 (0)