Merge pull request #3701 from devsnd/contacts-0.05

Contacts 0.05: Nicer UI, Refactoring, new icon
master
Rob Pilling 2024-12-24 17:59:53 +00:00 committed by GitHub
commit 62869129ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 75 additions and 99 deletions

View File

@ -2,3 +2,4 @@
0.02: Minor code improvements 0.02: Minor code improvements
0.03: Minor code improvements 0.03: Minor code improvements
0.04: Allow calling contacts from the app, Refactoring 0.04: Allow calling contacts from the app, Refactoring
0.05: Nicer UI, Refactoring, new icon

View File

@ -1,6 +1,6 @@
# Contacts # Contacts
This app provides a common way to set up the `contacts.json` file. View, edit and call contacts on your bangle.js. Calling is done via the bluetooth connection to your android phone.
## Contacts JSON file ## Contacts JSON file
@ -10,13 +10,15 @@ has the following contents:
``` ```
[ [
{
"name":"NONE"
},
{ {
"name":"First Last", "name":"First Last",
"number":"123456789", "number":"123456789",
} },
{
"name": "James Bond",
"number":"555-007",
},
...
] ]
``` ```
@ -27,3 +29,11 @@ the contact editor. The editor downloads and displays the current
`contacts.json` file. Clicking the `Edit` button beside an entry `contacts.json` file. Clicking the `Edit` button beside an entry
causes the entry to be deleted from the list and displayed in the edit causes the entry to be deleted from the list and displayed in the edit
boxes. It can be restored - by clicking the `Add` button. boxes. It can be restored - by clicking the `Add` button.
# Icons
<a target="_blank" href="https://icons8.com/icon/85059/phone">Phone</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
<a target="_blank" href="https://icons8.com/icon/362/trash-can">Delete Button</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
<a target="_blank" href="https://icons8.com/icon/iwE4yCawoyKM/call-list">Call List</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwwcBkmSpIC/AVsJCJ+AQaCZBCOeACKGQLKGQBA0ggARPJ4IRsYo0ggR9IoAIGiRiIpEECJsAiACBBYoRGpEAI4JBFI47CBLIRlDHYJrGYQIRCwQICL4MQOgx9GboUSeQ4RFwAFBiSGHCIo4CiVIWZyPICP4RaRIQROgARHdIwICoIIFkDpGBAKqHgGACI0AyVIggIDoEEMQ1ICINJCIj4CfwIREBwUgQYYOCfYoFDJQKDFCIopEO4RoDKAqJHRhAC/ATA=")) require("heatshrink").decompress(atob("mEwwZC/ABcN23btoCG7ARFBw4CDCP4RegYRQjY1RgE2LMlsHY4RIsBfHLJBxICKxrDCJxHQCK59LBYYRBa59sgzXPCJwLDwACCgENCJewjbaBgEBCJkDLgIRIO4vABIQRN7ARKNYaSELJo4EPpgCHCAjjGYpwRNLIzFPCP4RnZwQRHd4YA/AA4A="))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 838 B

View File

@ -1,14 +1,14 @@
/* contacts.js */
var Layout = require("Layout"); var Layout = require("Layout");
var wp = require('Storage').readJSON("contacts.json", true) || []; var contacts = require('Storage').readJSON("contacts.json", true) || [];
function writeContacts() { function writeContacts() {
require('Storage').writeJSON("contacts.json", wp); require('Storage').writeJSON("contacts.json", contacts);
} }
function callNumber (number) { function callNumber (number) {
E.showMessage('Calling ' + number + '...');
setTimeout(() => mainMenu(), 2000);
Bluetooth.println(JSON.stringify({ Bluetooth.println(JSON.stringify({
t:"intent", t:"intent",
target:"activity", target:"activity",
@ -17,35 +17,49 @@ function callNumber (number) {
categories:["android.intent.category.DEFAULT"], categories:["android.intent.category.DEFAULT"],
data: 'tel:' + number, data: 'tel:' + number,
})) }))
} }
function mainMenu() { function mainMenu() {
var menu = { var menu = {
"": {
"title": "Contacts",
},
"< Back" : Bangle.load "< Back" : Bangle.load
}; };
if (!wp.length) { if (!contacts.length) {
menu['No Contacts'] = () => {}; menu['No Contacts'] = () => {};
} else {
for (const e of wp) {
const closureE = e;
menu[e.name] = () => showContact(closureE);
} }
} contacts.forEach((e, idx) => {
menu["Add"] = addContact; menu[e.name] = () => showContact(idx)
menu["Remove"] = removeContact; })
menu["Add Contact"] = addContact;
g.clear(); g.clear();
E.showMenu(menu); E.showMenu(menu);
} }
function showContact(i) { function showContact(idx) {
g.clear(); g.clear();
var name = contacts[idx].name;
let longName = g.setFont("6x8:2").stringWidth(name) >= g.getWidth();
var number = contacts[idx].number;
let longNumber = g.setFont("6x8:2").stringWidth(number) >= g.getWidth();
(new Layout ({ (new Layout ({
type:"v", type:"v",
c: [ c: [
{type:"txt", font:"10%", pad:1, fillx:1, filly:1, label: i["name"] + "\n" + i["number"]}, {type: 'h', filly: 3, fillx:1, c: [
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "Call", cb: l => callNumber(i['number'])}, {type:"btn", font:"6x8", pad:1, fillx:1, filly:1, label: "<- Back to list", cb: mainMenu},
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "Back to list", cb: mainMenu} {type:"btn", pad:1, fillx:1, filly:3, src: require("heatshrink").decompress(atob("jUawYGDgVJkgQGBAOSBAsJkALBBIoaCDogaCAQYXBgIIFkmAC4IIFyVAgAIGGQUJHwo4FAo2QBwICDNAVAkgCEEAYUFEAQUFE34mRPwgmEcYgmDUg8AgjLGgAA==")),
cb: () => (
E.showPrompt("Delete Contact '" + name + "'?", )
.then((res) => { if (res) { deleteContact(idx) } else { mainMenu() } })
)
},
]},
{type:"txt", font:longName ? "6x8" : "6x8:2", pad:1, fillx:2, filly:3, label: longName ? name.slice(0, name.length/2) + '\n' + name.slice(name.length/2) : name},
{type:"txt", font: "6x8:2", pad:1, fillx:2, filly:3, label: longNumber ? number.slice(0, number.length/2) + '\n' + number.slice(number.length/2) : number},
{type: 'h', filly: 3, fillx:1, c: [
{type:"btn", pad:1, fillx:1, filly:3, src:atob("GBiBAAAAAAAAAAAAAB8AAB+AAB+AAB+AAB+AAA+AAA8AAA4AAAYAAAcAAAMAAAGAAAHB8ADz+AA/+AAf+AAH+AAA+AAAAAAAAAAAAA=="), cb: l => callNumber(number)},
]},
], ],
lazy:true lazy:true
})).render(); })).render();
@ -92,76 +106,27 @@ function showNumpad() {
}); });
} }
function removeContact() { function deleteContact(idx) {
var menu = { contacts.splice(idx, 1);
"" : {title : "Select Contact"},
"< Back" : mainMenu
};
if (wp.length===0) Object.assign(menu, {"No Contacts":""});
else {
wp.forEach((val, card) => {
const name = wp[card].name;
menu[name]=()=>{
E.showMenu();
var confirmRemove = new Layout (
{type:"v", c: [
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:"Delete"},
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:name},
{type:"h", c: [
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "YES", cb:l=>{
wp.splice(card, 1);
writeContacts(); writeContacts();
mainMenu(); mainMenu();
}},
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: " NO", cb:l=>{mainMenu();}}
]}
], lazy:true});
g.clear();
confirmRemove.render();
};
});
}
E.showMenu(menu);
}
function addNewContact(name) {
g.clear();
showNumpad().then((number) => {
wp.push({name: name, number: number});
writeContacts();
mainMenu();
})
}
function tryAddContact(name) {
if (wp.filter((e) => e.name === name).length) {
E.showMenu();
var alreadyExists = new Layout (
{type:"v", c: [
{type:"txt", font:Math.min(15,100/name.length)+"%", pad:1, fillx:1, filly:1, label:name},
{type:"txt", font:"12%", pad:1, fillx:1, filly:1, label:"already exists."},
{type:"h", c: [
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "REPLACE", cb:l=>{ addNewContact(name); }},
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "CANCEL", cb:l=>{mainMenu();}}
]}
], lazy:true});
g.clear();
alreadyExists.render();
return;
}
addNewContact(name);
} }
function addContact() { function addContact() {
require("textinput").input({text:""}).then(name => { require("textinput").input({text:""})
.then(name => {
name = name.trim();
if (name !== "") { if (name !== "") {
tryAddContact(name); g.clear();
} else showNumpad().then((number) => {
contacts.push({name: name, number: number});
writeContacts();
mainMenu(); mainMenu();
})
} else {
E.showMessage("Invalid name");
setTimeout(() => mainMenu(), 1000);
}
}); });
} }

View File

@ -33,7 +33,7 @@
</style> </style>
</head> </head>
<body> <body>
<h1>Contacts v.2</h1> <h1>Contacts</h1>
<div class="flex-col"> <div class="flex-col">
<div id="statusarea"> <div id="statusarea">
<button id="download" class="btn btn-error">Reload</button> <button id="upload" class="btn btn-primary">Upload</button> <button id="download" class="btn btn-error">Reload</button> <button id="upload" class="btn btn-primary">Upload</button>

View File

@ -1,7 +1,7 @@
{ "id": "contacts", { "id": "contacts",
"name": "Contacts", "name": "Contacts",
"version": "0.04", "version": "0.05",
"description": "Provides means of storing user contacts, viewing/editing them on device and from the App loader", "description": "View, edit and call contacts on device and from the App loader",
"icon": "app.png", "icon": "app.png",
"tags": "tool", "tags": "tool",
"supports" : ["BANGLEJS2"], "supports" : ["BANGLEJS2"],