Untitled
unknown
plain_text
3 years ago
7.1 kB
18
Indexable
import { APIs } from '../consts/api';
import { CallLog, FavoriteInfo, PhoneNumber } from '../types/api';
import { PageRes, getData } from '../utils/request';
import Contacts from 'react-native-contacts';
import { CallRecord, Contact, NumberFavorites } from '../models';
import { getAuthToken } from 'utils/token';
export function syncCallLog(realm: Realm) {
return getData<PageRes<CallLog>>(APIs.CALL_RECENTS + `?ver=${Date.now()}&skip=0&take=100`).then(
(res) => {
realm.write(() => {
res.data.forEach((call) => {
realm.create<CallRecord>(
'CallRecord',
{
id: call.id,
contact: call.contact,
contact_name: call.name,
outgoing: call.outgoing,
video: call.type == 'video',
created_at: call.created_at,
state: call.state,
duration: call.duration,
},
'modified'
);
});
});
}
);
}
export function syncFavorites(realm: Realm) {
return getData<PageRes<FavoriteInfo>>(APIs.FAVORITES + `?ver=${Date.now()}&skip=0&take=100`).then(
(res) => {
realm.write(() => {
let data = realm.objects('NumberFavorites');
realm.delete(data);
res.data.forEach((f) => {
realm.create<NumberFavorites>(
'NumberFavorites',
{
id: f.id,
number: f.number,
created_at: f.created_at,
},
'modified'
);
});
});
}
);
}
function build_name(c: Contacts.Contact) {
let parts = [];
if (c.givenName) {
parts.push(c.givenName);
}
if (c.middleName) {
parts.push(c.middleName);
}
if (c.familyName) {
parts.push(c.familyName);
}
if (c.company) {
parts.push(c.company);
}
if (parts.length == 0 && c.phoneNumbers.length > 0) {
parts.push(c.phoneNumbers[0].number);
}
return parts.join(' ');
}
// normalize phone number, remove all space and contruoy code
function normalize_number(number: string) {
return number.replace(/\s/g, '');
}
export async function syncContact(realm: Realm): Promise<string | null> {
let now_ms = Date.now();
let updated: Map<string, boolean> = new Map();
let token = await getAuthToken();
let promise1 = async () => {
try {
let res = await Contacts.getAll();
return { res, error: null };
} catch (e) {
return { res: [], error: 'Contacts permission denied' };
}
};
let promise2 = async () => {
if (!token) return;
try {
let res = await getData<PageRes<PhoneNumber>>(
APIs.CONTACTS + `?ver=${Date.now()}&skip=0&take=1000`
);
console.log('23232323', res);
return { res, error: null };
} catch (e) {
return { res: { data: [] }, error: 'Cannot get remote contacts' };
}
};
return Promise.all([promise1(), promise2()]).then(([res1, res2]) => {
const local_contacts = res1.res;
const local_error = res1.error;
const remote_contacts = res2?.res;
const remote_error = res2?.error;
// avoid contacts duplicate
let map = new Map<string, Contacts.Contact>();
let local_contacts2: Contacts.Contact[] = [];
local_contacts.forEach((contact) => {
if (contact.phoneNumbers.length > 0) {
let number = normalize_number(contact.phoneNumbers[0].number);
if (!map.has(number)) {
updated.set(number, true);
map.set(number, contact);
local_contacts2.push(contact);
}
}
});
// contacts returned
realm.write(() => {
local_contacts2.forEach((contact) => {
if (contact.phoneNumbers.length > 0) {
let name = build_name(contact);
let number = normalize_number(contact.phoneNumbers[0].number);
let exiting = realm.objectForPrimaryKey<Contact>('Contact', number);
if (!exiting) {
console.log('create local contact:', name);
realm.create<Contact>(
'Contact',
{
group_label: name.charAt(0).toUpperCase(),
number,
name: name,
name_sort: name.toLowerCase(),
last_updated: now_ms,
is_local: true,
},
'modified'
);
} else if (name != exiting.name || !exiting.is_local) {
console.log(
'update local contact:',
name,
exiting.name,
name != exiting.name,
exiting.is_local
);
exiting.group_label = name.charAt(0).toUpperCase();
exiting.name = name;
exiting.name_sort = name.toLowerCase();
exiting.last_updated = now_ms;
exiting.is_local = true;
}
}
});
console.log('debug contact', remote_contacts);
remote_contacts?.data.forEach((number) => {
updated.set(number.number, true);
let name = number.name || number.number;
let remote_version = number.updated_at || number.created_at;
let exiting = realm.objectForPrimaryKey<Contact>('Contact', number.number);
if (!exiting) {
console.log('create remote contact:', number.number);
realm.create<Contact>(
'Contact',
{
group_label: name.charAt(0).toUpperCase(),
number: number.number,
name,
avatar: number.avatar,
is_register: number?.is_register,
name_sort: name.toLowerCase(),
last_updated: now_ms,
},
'modified'
);
} else if (!exiting.is_local && exiting.last_updated < remote_version) {
console.log('update remote contact:', number.number);
exiting.group_label = name.charAt(0).toUpperCase();
exiting.name = name;
exiting.name_sort = name.toLowerCase();
exiting.last_updated = now_ms;
} else {
if (exiting.is_local) {
exiting.group_label = name.charAt(0).toUpperCase();
exiting.name = name;
exiting.name_sort = name.toLowerCase();
exiting.avatar = number?.avatar;
exiting.is_register = number?.is_register;
}
}
});
//clean up which contact not shown in updated
realm.objects<Contact>('Contact').forEach((contact) => {
if (!updated.has(contact.number)) {
console.log('delete contact:', contact.number, contact.name);
if (contact.is_local && !local_error) {
realm.delete(contact);
}
if (!contact.is_local && !remote_error) {
realm.delete(contact);
}
}
});
});
return local_error || remote_error || null;
});
}
Editor is loading...