Skip to content

Commit e56d8aa

Browse files
committed
feat: Minor release v2.1.1
- Introduced search functionality for contacts and country selector - Added multi-delete and selection-based contact sharing features - Improved overall app performance and responsiveness - Fixed various bugs for enhanced stability - Refined and modernized user interface for a better experience
1 parent b5554b4 commit e56d8aa

35 files changed

+1354
-870
lines changed

.github/workflows/android-release.yml

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,44 @@ jobs:
7575
draft: false
7676
prerelease: false
7777
body: |
78-
## What's Changed
79-
- Android release build for version ${{ steps.tag.outputs.tag }}
80-
81-
## APK Downloads
82-
This release includes split APKs for different architectures:
83-
- **arm64-v8a**: For modern 64-bit ARM devices (recommended for most users)
84-
- **armeabi-v7a**: For older 32-bit ARM devices
85-
- **x86_64**: For 64-bit x86 devices (emulators, some tablets)
86-
- **x86**: For 32-bit x86 devices (older emulators)
87-
88-
Download the appropriate APK for your device architecture.
78+
# 🚀 Alternate ${{ steps.tag.outputs.tag }} – Feature & Improvement Release
79+
80+
## ✨ What's New in ${{ steps.tag.outputs.tag }}
81+
82+
- **Search Functionality:**
83+
Added search for contacts and country selector for faster access.
84+
85+
- **Multi-Delete & Contact Sharing:**
86+
Added multi-delete and selection-based contact sharing features for easier contact management.
87+
88+
- **Performance Improvements:**
89+
Enhanced app speed and responsiveness.
90+
91+
- **Bug Fixes:**
92+
Fixed various issues for improved stability.
93+
94+
- **UI Enhancements:**
95+
Refined and modernized the user interface for a better experience.
96+
97+
## 📦 Download Options
98+
99+
Choose the APK that matches your device architecture:
100+
101+
- **ARM64 (64-bit)** – Recommended for most modern devices
102+
- **ARM (32-bit)** – For older Android devices
103+
- **x86 (64-bit)** – For Intel-based Android devices/emulators
104+
- **x86 (32-bit)** – For older Intel-based devices
105+
106+
## 🔧 Installation
107+
108+
1. Download the appropriate APK for your device
109+
2. Enable "Install from unknown sources" in your Android settings
110+
3. Install the APK file
111+
112+
## 📋 System Requirements
113+
114+
- Android 7.0 (API level 24) or higher
115+
- Permissions: Contacts, Phone
89116
90117
- name: Upload arm64-v8a APK
91118
uses: actions/upload-release-asset@v1

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 5
105-
versionName "2.0.1"
104+
versionCode 6
105+
versionName "2.1.1"
106106
}
107107

108108
signingConfigs {

app.json

Lines changed: 1 addition & 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.0.1",
5+
"version": "2.1.1",
66
"orientation": "portrait",
77
"scheme": "alternate",
88
"userInterfaceStyle": "automatic",

app/_layout.tsx

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { CountrySelectorProvider } from "@/components/country-selector-provider";
21
import ErrorBoundary from "@/components/ErrorBoundary";
32
import CustomNavigationBar from "@/components/navigation-bar";
43
import { useTheme } from "@/hooks/useTheme";
4+
import "@/services/sheets"; // Ensure sheets are registered
55
import useContactStore from "@/store/contactStore";
66
import { ThemeProvider } from "@react-navigation/native";
7-
import { router, SplashScreen, Stack } from "expo-router";
7+
import { SplashScreen, Stack } from "expo-router";
88
import { StatusBar } from "expo-status-bar";
99
import { useEffect, useState } from "react";
10+
import { SheetProvider } from "react-native-actions-sheet";
1011
import { GestureHandlerRootView } from "react-native-gesture-handler";
1112
import { PaperProvider } from "react-native-paper";
1213

@@ -42,27 +43,12 @@ export default function RootLayout() {
4243
<ErrorBoundary>
4344
<PaperProvider theme={paperTheme}>
4445
<ThemeProvider value={paperTheme}>
45-
<CountrySelectorProvider>
46+
<SheetProvider context="global">
4647
<Stack
4748
screenOptions={{
4849
header: (props) => <CustomNavigationBar {...props} />,
4950
}}
5051
>
51-
<Stack.Screen
52-
name="index"
53-
options={{
54-
title: "Contacts",
55-
header: (props) => (
56-
<CustomNavigationBar
57-
action={{
58-
icon: "cog",
59-
onPress: () => router.push("/settings"),
60-
}}
61-
{...props}
62-
/>
63-
),
64-
}}
65-
/>
6652
<Stack.Screen
6753
name="new-contact"
6854
options={{
@@ -92,7 +78,7 @@ export default function RootLayout() {
9278
}}
9379
/>
9480
</Stack>
95-
</CountrySelectorProvider>
81+
</SheetProvider>
9682
</ThemeProvider>
9783
<StatusBar style={paperTheme.dark ? "light" : "dark"} />
9884
</PaperProvider>

app/edit-contact.tsx

Lines changed: 17 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
import Material3Avatar from "@/components/material3-avatar";
22
import PhoneNumberInput from "@/components/phone-number-input";
3+
import { additionalFields } from "@/constants/AdditionalFields";
34
import { getAvatarColor } from "@/lib/avatar-utils";
45
import { getCountryByCode } from "@/lib/countries";
56
import { Contact, ContactFormData } from "@/lib/types";
67
import { getFormattedDate, getVisibleFields, trimDialCode } from "@/lib/utils";
78
import useContactStore from "@/store/contactStore";
8-
import BottomSheet, {
9-
BottomSheetBackdrop,
10-
BottomSheetScrollView,
11-
BottomSheetView,
12-
} from "@gorhom/bottom-sheet";
139
import { router, useLocalSearchParams } from "expo-router";
1410
import React, { useState } from "react";
1511
import { Controller, useForm } from "react-hook-form";
@@ -22,20 +18,22 @@ import {
2218
StyleSheet,
2319
View,
2420
} from "react-native";
21+
import { SheetManager } from "react-native-actions-sheet";
2522
import DatePicker from "react-native-date-picker";
2623
import {
2724
Button,
2825
HelperText,
29-
List,
3026
Portal,
3127
Snackbar,
3228
Text,
3329
TextInput,
3430
useTheme,
3531
} from "react-native-paper";
32+
import { useSafeAreaInsets } from "react-native-safe-area-context";
3633

3734
export default function EditContactScreen() {
3835
const theme = useTheme();
36+
const insets = useSafeAreaInsets();
3937
const { contact: contactParam, index } = useLocalSearchParams();
4038

4139
// Parse the contact from JSON string
@@ -58,27 +56,6 @@ export default function EditContactScreen() {
5856
contact?.birthday ? new Date(contact.birthday) : new Date()
5957
);
6058

61-
// Bottom sheet ref and snap points
62-
const bottomSheetModalRef = React.useRef<BottomSheet>(null);
63-
64-
const additionalFields = [
65-
{ key: "prefix", label: "Prefix", icon: "account-arrow-left-outline" },
66-
{ key: "suffix", label: "Suffix", icon: "account-arrow-right-outline" },
67-
{ key: "email", label: "Email", icon: "email-outline" },
68-
{ key: "notes", label: "Notes", icon: "note-text-outline" },
69-
{ key: "website", label: "Website", icon: "link" },
70-
{ key: "birthday", label: "Birthday", icon: "cake-variant-outline" },
71-
{ key: "nickname", label: "Nickname", icon: "account-heart-outline" },
72-
];
73-
74-
const openBottomSheet = React.useCallback(() => {
75-
bottomSheetModalRef.current?.expand();
76-
}, []);
77-
78-
const closeBottomSheet = React.useCallback(() => {
79-
bottomSheetModalRef.current?.close();
80-
}, []);
81-
8259
const [avatarBackgroundColor, avatarTextColor] = getAvatarColor(
8360
letter,
8461
theme.dark,
@@ -117,17 +94,6 @@ export default function EditContactScreen() {
11794

11895
const onDismissSnackBar = () => setVisible(false);
11996

120-
const toggleField = (fieldKey: string) => {
121-
const newVisibleFields = new Set(visibleFields);
122-
if (newVisibleFields.has(fieldKey)) {
123-
newVisibleFields.delete(fieldKey);
124-
} else {
125-
newVisibleFields.add(fieldKey);
126-
}
127-
setVisibleFields(newVisibleFields);
128-
closeBottomSheet();
129-
};
130-
13197
const removeFieldAndReset = (fieldKey: string) => {
13298
const newVisibleFields = new Set(visibleFields);
13399
newVisibleFields.delete(fieldKey);
@@ -252,7 +218,7 @@ export default function EditContactScreen() {
252218
});
253219

254220
if (success) {
255-
router.replace("/");
221+
router.dismissAll();
256222
} else {
257223
setVisible(true);
258224
}
@@ -272,9 +238,14 @@ export default function EditContactScreen() {
272238
return (
273239
<KeyboardAvoidingView
274240
behavior={Platform.OS === "ios" ? "padding" : "height"}
275-
style={styles.container}
241+
style={[styles.container, { paddingBottom: insets.bottom }]}
276242
>
277-
<ScrollView contentContainerStyle={styles.scrollContent}>
243+
<ScrollView
244+
contentContainerStyle={[
245+
styles.scrollContent,
246+
{ paddingBottom: insets.bottom },
247+
]}
248+
>
278249
<View style={styles.formContainer}>
279250
<Material3Avatar
280251
letter={letter}
@@ -369,7 +340,11 @@ export default function EditContactScreen() {
369340
<View style={styles.buttonContainer}>
370341
<Button
371342
mode="contained-tonal"
372-
onPress={openBottomSheet}
343+
onPress={() =>
344+
SheetManager.show("additional-field-sheet", {
345+
payload: { visibleFields, setVisibleFields },
346+
})
347+
}
373348
style={styles.addFieldButton}
374349
labelStyle={{ fontSize: 16 }}
375350
disabled={
@@ -393,59 +368,6 @@ export default function EditContactScreen() {
393368
</ScrollView>
394369

395370
<Portal>
396-
{/* Add Fields Bottom Sheet */}
397-
<BottomSheet
398-
ref={bottomSheetModalRef}
399-
enableDynamicSizing={false}
400-
snapPoints={["60%"]}
401-
index={-1}
402-
enablePanDownToClose={true}
403-
backdropComponent={(props) => (
404-
<BottomSheetBackdrop
405-
{...props}
406-
appearsOnIndex={0}
407-
disappearsOnIndex={-1}
408-
/>
409-
)}
410-
backgroundStyle={[
411-
{ backgroundColor: theme.colors.elevation.level2 },
412-
styles.bottomSheetBackground,
413-
]}
414-
handleIndicatorStyle={{
415-
backgroundColor: theme.colors.onSurfaceVariant,
416-
}}
417-
>
418-
<BottomSheetView
419-
style={[
420-
styles.header,
421-
{
422-
borderBottomColor: theme.colors.outline,
423-
backgroundColor: theme.colors.elevation.level2,
424-
},
425-
]}
426-
>
427-
<Text
428-
variant="headlineSmall"
429-
style={[styles.title, { color: theme.colors.onSurface }]}
430-
>
431-
Choose fields to add
432-
</Text>
433-
</BottomSheetView>
434-
<BottomSheetScrollView style={styles.bottomSheetContent}>
435-
{additionalFields
436-
.filter((field) => !visibleFields.has(field.key))
437-
.map((field, index) => (
438-
<List.Item
439-
key={field.key}
440-
title={field.label}
441-
left={() => <List.Icon icon={field.icon} />}
442-
onPress={() => toggleField(field.key)}
443-
style={styles.list}
444-
/>
445-
))}
446-
</BottomSheetScrollView>
447-
</BottomSheet>
448-
449371
<Snackbar
450372
visible={visible}
451373
onDismiss={onDismissSnackBar}
@@ -459,13 +381,6 @@ export default function EditContactScreen() {
459381
>
460382
{updateError || "An error occurred"}
461383
</Snackbar>
462-
{/* <Dialog visible={visible} onDismiss={hideDialog}>
463-
<Dialog.Icon icon="alert" />
464-
<Dialog.Title >This is a title</Dialog.Title>
465-
<Dialog.Content>
466-
<Text variant="bodyMedium">This is simple dialog</Text>
467-
</Dialog.Content>
468-
</Dialog> */}
469384
</Portal>
470385
</KeyboardAvoidingView>
471386
);
@@ -481,7 +396,6 @@ const styles = StyleSheet.create({
481396
},
482397
formContainer: {
483398
flex: 1,
484-
padding: 16,
485399
paddingHorizontal: 16,
486400
gap: 16,
487401
},

0 commit comments

Comments
 (0)