diff options
| author | Adam Soltys <[email protected]> | 2023-04-21 20:50:19 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-04-21 20:50:19 -0700 |
| commit | 46a68609068ff360d32852c42ead77a273027c57 (patch) | |
| tree | 115362b713df62578ec9e35b6bc7fbae27bd3d21 /src | |
| parent | a71f89b972ef05fcda406afa4e346ee54624a958 (diff) | |
| parent | 92c70d8350dab3de8e786bdad1c0a8f991cd8dbc (diff) | |
| download | coinos-ui-46a68609068ff360d32852c42ead77a273027c57.tar.gz coinos-ui-46a68609068ff360d32852c42ead77a273027c57.zip | |
Merge branch 'master' into hashme
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/LocationsMap.svelte | 44 | ||||
| -rw-r--r-- | src/components/Numpad.svelte | 2 | ||||
| -rw-r--r-- | src/lib/socket.js | 2 | ||||
| -rw-r--r-- | src/lib/store.js | 2 | ||||
| -rw-r--r-- | src/lib/translations/index.js | 19 | ||||
| -rw-r--r-- | src/lib/translations/lang.json | 3 | ||||
| -rw-r--r-- | src/locales/el.json | 283 | ||||
| -rw-r--r-- | src/routes/(app)/+layout.svelte | 43 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/settings/[...tab]/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/(app)/payment/[id]/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/(app)/register/+page.server.js | 2 | ||||
| -rw-r--r-- | src/routes/(app)/send/+layout.svelte | 3 | ||||
| -rw-r--r-- | src/routes/(app)/send/[...text]/+page.server.js | 4 | ||||
| -rw-r--r-- | src/routes/+page.svelte | 5 |
14 files changed, 344 insertions, 72 deletions
diff --git a/src/components/LocationsMap.svelte b/src/components/LocationsMap.svelte index 37454731..fcc672e8 100644 --- a/src/components/LocationsMap.svelte +++ b/src/components/LocationsMap.svelte @@ -38,43 +38,12 @@ locations = locations.filter( (location) => - location['osm_json'].tags && location['osm_json'].tags['payment:hashme'] === 'yes' + location['osm_json'].tags && + location['osm_json'].tags['payment:hashme'] === 'yes' && + location['osm_json'].lat && + location['osm_json'].lon ); - /* const locations = [ - { - lat: 49.27034, - lng: -123.141373, - info: 'Rolf Vancouver <br> 1628 W 1st Ave #231, Vancouver <br> <a href="https://www.rolfbodywork.com" target="_blank" rel="noreferrer">www.rolfbodywork.com</a>' - }, - { lat: 49.26419, lng: -123.15702, info: 'Tacos Jorge <br> 2287 W Broadway, Vancouver' }, - { - lat: 49.28273, - lng: -123.120735, - info: 'Engage Strategies <br> <a href="https://www.linkedin.com/in/shauna-collister-32905214" target="_blank" rel="noreferrer">LinkedIn</a>' - }, - { - lat: 49.28134, - lng: -123.02373, - info: 'Lumota Collection <br> Clothing Design/Upcycling - Appointment Only <br> <a href="tel:778-726-3776">778-726-3776</a> <br> 369 Boundary Rd, Vancouver, BC V5K 2B1 <br> <a href="https://www.instagram.com/lumotacollection/" target="_blank" rel="noreferrer">IG: Lumotacollection</a> <br> <a href="https://www.facebook.com/LumotaCollection/posts" target="_blank" rel="noreferrer">FB: Lumotacollection</a>' - }, - { - lat: 49.22643, - lng: -122.93085, - info: 'Goodwin Contracting <br> Project Management/Consulting - Appointment Only <br> <a href="tel:403-812-1085">403-812-1085</a> <br> 8017 17th Ave, Burnaby, BC V3N 1M5' - }, - { - lat: 51.04813, - lng: -114.07999, - info: 'Goodwin Contracting <br> Project Management/Consulting - Appointment Only <br> <a href="tel:403-812-1085">403-812-1085</a> <br> 8017 17th Ave, Burnaby, BC V3N 1M5' - }, - { - lat: 49.2677, - lng: -123.10124, - info: 'General Strike Coffee <br> Artisan coffee shop <br> 1965 Main St, Vancouver, BC V5T 2K6 <br> <a href="https://www.instagram.com/generalstrikecoffee/" target="_blank" rel="noreferrer">IG: generalstrikecoffee</a>' - } - ];*/ - L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png', { maxZoom: 18, subdomains: ['a', 'b', 'c', 'd'] @@ -100,12 +69,9 @@ let markers = new MarkerClusterGroup(); locations.forEach((location) => { - if (location['deleted_at']) { - return; - } + if (location['deleted_at']) return; location = location['osm_json']; - let marker = L.marker([location.lat, location.lon]); marker.bindPopup( diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte index 82512678..5ea1418c 100644 --- a/src/components/Numpad.svelte +++ b/src/components/Numpad.svelte @@ -31,7 +31,7 @@ AUD: '$', NZD: '$', MXN: '$', - BRL: '$', + BRL: 'R$', HKD: '$', TWD: '$', JPY: '¥', diff --git a/src/lib/socket.js b/src/lib/socket.js index aef8a513..e8859fa6 100644 --- a/src/lib/socket.js +++ b/src/lib/socket.js @@ -7,7 +7,7 @@ import { browser } from '$app/environment'; let socket, token; -export const auth = () => token && send('login', token) && send('heartbeat'); +export const auth = () => token && send('login', token); export const send = (type, data) => { socket?.readyState === 1 && socket.send(JSON.stringify({ type, data })); diff --git a/src/lib/store.js b/src/lib/store.js index ce984b17..4e88c90c 100644 --- a/src/lib/store.js +++ b/src/lib/store.js @@ -46,7 +46,7 @@ export const newPayment = persistLocal('newPayment'); export const password = persistLocal('password'); export const passwordPrompt = writable(); export const payments = persistLocal('transactions', []); -export const pin = persistSession('pin', undefined); +export const pin = writable(); export const rate = writable(); export const request = writable(); export const requestRedirect = writable(); diff --git a/src/lib/translations/index.js b/src/lib/translations/index.js index ea92192b..8d1b9feb 100644 --- a/src/lib/translations/index.js +++ b/src/lib/translations/index.js @@ -28,9 +28,9 @@ const config = { loader: async () => (await import('../../locales/en.json')).default }, { - locale: 'fa', + locale: 'es', key: '', - loader: async () => (await import('../../locales/fa.json')).default + loader: async () => (await import('../../locales/es.json')).default }, { locale: 'fr', @@ -38,11 +38,6 @@ const config = { loader: async () => (await import('../../locales/fr.json')).default }, { - locale: 'es', - key: '', - loader: async () => (await import('../../locales/es.json')).default - }, - { locale: 'pt', key: '', loader: async () => (await import('../../locales/pt.json')).default @@ -56,6 +51,16 @@ const config = { locale: 'zh', key: '', loader: async () => (await import('../../locales/zh.json')).default + }, + { + locale: 'fa', + key: '', + loader: async () => (await import('../../locales/fa.json')).default + }, + { + locale: 'el', + key: '', + loader: async () => (await import('../../locales/el.json')).default } ] }; diff --git a/src/lib/translations/lang.json b/src/lib/translations/lang.json index cbf1ce4a..0acc1de6 100644 --- a/src/lib/translations/lang.json +++ b/src/lib/translations/lang.json @@ -5,5 +5,6 @@ "de": "Deutsch", "pt": "Português", "zh": "中国人", - "fa": "فارسی " + "fa": "فارسی ", + "el": "Ελληνικά" } diff --git a/src/locales/el.json b/src/locales/el.json new file mode 100644 index 00000000..28f7db2b --- /dev/null +++ b/src/locales/el.json @@ -0,0 +1,283 @@ +{ + "404": { + "404": "404", + "pageNotFound": "Page not found." + }, + "about": { + "header": "About", + "p1": "Coinos is an open source bitcoin payment app. Development started in Vancouver in September 2012 as a way to provide local merchants with a convenient way to accept bitcoin payments.", + "p2": "You can download the source code to run an instance and connect it to your own bitcoin and lightning nodes. We'll help you get started being a benevolent custodian and payments provider for your community.", + "p3": "Account transfers amongst users on our server are done off-chain so they're completely free, instant, and unlimited.", + "team": { + "header": "The Team", + "adam": { + "name": "Adam Soltys", + "position": "Chief Technical Officer", + "bio": "Adam is a web developer and bitcoin enthusiast who believes sound money is key to increasing global prosperity. He lives in North Vancouver with his wife Chelsea and two children." + }, + "cole": { + "name": "Cole", + "position": "Certified Bitcoin Professional", + "bio": "Cole is a driven individual with a passion for freedom. He came across bitcoin in 2016 and studied it in depth. Now he wants to introduce the lightning network to as many users as possible." + } + }, + "locations": { + "header": "Locations", + "description": "Here are some businesses that are accepting bitcoin with Coinos. We hope that yours will be next!" + } + }, + "error": { + "header": "Error", + "message": "Please try again or contact support.", + "signIn": "Please sign in to continue." + }, + "faq": { + "header": "FAQ", + "cost": { + "question": "What does it cost?", + "answer": "It's free to register an account and receive payments. We charge a 0.1% conversion fee if you withdraw regular bitcoin to lightning or vice versa." + }, + "compatibility": { + "question": "Do I need any special device or software?", + "answer": "No. Coinos is web based, so as long as you have an internet connection and a web browser, it works anywhere. Retail merchants might use it on a phone or a tablet." + }, + "safety": { + "question": "When do my funds settle?", + "answer": "Lightning payments are settled instantly. You can withdraw your balance to another wallet or exchange immediately once funds are received." + } + }, + "footer": { + "company": "Company", + "followUs": "Follow Us", + "github": "GitHub", + "linktree": "Linktree", + "jobs": "Jobs", + "support": "Support", + "telegram": "Telegram", + "twitter": "Twitter", + "documentation": "Documentation" + }, + "howItWorks": { + "header": "How it works", + "step1": { + "header": "1. Create your account", + "description": "A username and password is all you need to get started." + }, + "step2": { + "header": "2. Ask for payments", + "description": "The same as you normally would, but with bitcoin." + }, + "step3": { + "header": "3. That's all!", + "description": "Spend your coin immediately or save it and watch it grow, the choice is yours." + } + }, + "invoice": { + "addTip": "Add a tip", + "addTipq": "Add a tip?", + "done": "Done", + "paymentSuccessful": "Payment received!", + "invoice": "Invoice", + "total": "Total", + "tip": "Tip" + }, + "jobs": { + "header": "Jobs", + "subheader": "Current Openings", + "pitch1": "Coinos is actively looking for developers to join our growing team (full-time or part-time, remote working OK).", + "pitch2": "Excited about working on open source bitcoin? Then take a look at our repositories on", + "github": "GitHub", + "pitch3": "If you think you can make an impact, we'd love to hear from you. Send us your resume to" + }, + "landing": { + "header_before_icon": "The", + "header_with_icon": "easiest", + "header_after_icon": "way to get started with bitcoin.", + "subheader": "A simple but powerful web wallet for everyone. No software or hardware required.", + "info1": { + "title": "Instant payments via Lightning", + "description": "We make it easy for merchants to receive retail payments. No waiting for bank settlements or worrying about chargebacks. Instant settlement, in seconds. Say goodbye to 3% credit card processing fees." + }, + "info2": { + "title": "Simple to use", + "description1": "Just enter an amount in your local currency, share the QR code and you’re done.", + "description2": "We do all the heavy lifting so you can focus on your business.", + "description3": "You always have the option of taking custody of your funds by withdrawing instantly at any time." + }, + "info3": { + "title": "Brand it your way!", + "description": "Customize your profile page look and feel, or keep it on default - it's totally up to you." + } + }, + "login": { + "optional": "Optional", + "token": "2FA Token", + "username": "Username", + "password": "Password", + "email": "Email", + "passwordRecommendation": "We recommend a long, random password generated with a password manager.", + "forgotUserOrPassword": "Forgot Username or Password?", + "haveAccount": "Already have an account?", + "noAccount": "Don't have an account?", + "register": "Register", + "signIn": "Sign In", + "failed": "Login failed" + }, + "nav": { + "profile": "Profile", + "startInSeconds": "Start in Seconds", + "account": "Account", + "signIn": "Sign In", + "signOut": "Sign Out", + "dashboard": "Dashboard", + "settings": "Settings", + "support": "Support" + }, + "newSiteHeader": "Join us at our <a href=\"/launch\" class=\"underline underline-offset-4 text-black hover:opacity-80\">launch party</a> in Vancouver on October 26! Looking for the old coinos? Visit <a href=\"https://classic.coinos.io\" class=\"underline underline-offset-4 text-black hover:opacity-80\">classic.coinos.io</a>", + "news": { + "header": "News", + "subheader": "Latest Updates", + "update1": "" + }, + "user": { + "bitcoin": "Bitcoin", + "lightning": "Lightning", + "invoice": "Invoice", + "unfollow": "Unfollow", + "following": "Following", + "follow": "Follow", + "followers": "Followers", + "remove": "Remove", + "noNotes": "No notes yet", + "message": "Message", + "messages": "Messages", + "feed": "Feed", + "notes": "Notes", + "pay": "Pay", + "scanToPayBTC": "Scan to pay with bitcoin", + "this": "This", + "lightningAddress": "lightning address", + "likeAnEmail": "is like an email for bitcoin. You can publish it on your website or business cards and use it multiple times.", + "dashboard": { + "go": "Go", + "dashboard": "Dashboard", + "accountBalance": "Account Balance", + "bitcoinPrice": "bitcoin Price:", + "conversionFeeWarning": "You will be charged a 1% withdrawal fee on the amount.", + "dataFromBinance": "Data from <span class=\"text-black\">Binance</span>.", + "fetchingRate": "fetching rate...", + "optionalNote": "Note (Optional)", + "send": "Send", + "receive": "Receive", + "withdraw": "Send", + "deposit": "Deposit", + "voucher": "Voucher" + }, + "receive": { + "lessThan1BTCWarning": "Please enter an amount less than 1 bitcoin.", + "showQR": "Show QR" + }, + "send": { + "contacts": "Contacts", + "scan": "Scan", + "paste": "Paste", + "next": "Next", + "placeholder": "Paste a bitcoin address, lightning invoice or coinos username" + }, + "settings": { + "saveSettings": "Save Settings", + "bannerImage": "Banner Image", + "profileImage": "Profile Image", + "oneTimeCode": "Enter one-time code", + "accountId": "Account Secret", + "header": "Settings", + "ACCOUNT": "ACCOUNT", + "POINT_OF_SALE": "PREFERENCES", + "SECURITY": "SECURITY", + "locale": "Language", + "username": "Username", + "email": "Email", + "newPassword": "Change Password", + "about": "About", + "aboutPlaceholder": "A little something about you or your business address and hours", + "emailNotifications": "Email Notifications", + "emailNotificationsDescription": "Get notified via email when a change occurs on your account or when people send you payments.", + "smsNotifications": "SMS Notifications", + "smsNotificationsDescription": "Coinos will send you text notifications when this is enabled.", + "theme": "Color Theme", + "tipPrompt": "Prompt for tips", + "tipPromptDescription": "Ask people if they want to add a tip before paying their invoices", + "displayName": "Display name", + "themeDescription": "Select from the default color themes.", + "localCurrency": "Currency", + "btcUnit": "Display bitcoin in:", + "bitcoin": "bitcoin", + "minutes": "minutes", + "hour": "hour", + "hours": "hours", + "satoshis": "Satoshis", + "securityPIN": "Security PIN", + "securityPINDescription": "Set a security pin that will be used to unlock your settings and to send outgoing payments.", + "setPIN": "Set PIN", + "autoLock": "Auto-Lock Timer", + "autoLockDescription": "Your account will go into a secure mode, requiring you to re-enter your credentials after a specified time:", + "twofa": "2-Factor Authentication", + "twofaDescription": "Add an extra level of security to your device by enabling 2-factor authentication.", + "twofaSetup": "Set up 2FA", + "twofaDisable": "Disable 2FA", + "select": "Select", + "verifyPIN": "Verify PIN", + "enablePIN": "Enable PIN", + "disablePIN": "Disable PIN" + }, + "support": { + "header": "Support", + "email": "Email", + "accountName": "Account Name", + "message": "Message", + "send": "Send" + } + }, + "payments": { + "amount": "Amount", + "date": "Date", + "id": "Transaction ID", + "details": "Transaction Details", + "header": "Payments", + "preimage": "Proof of payment", + "type": "Type", + "time": "Time", + "sent": "Sent", + "received": "Received", + "empty": "No transactions yet.", + "send": "Send", + "next": "Next", + "sendersChoice": "Sender's choice", + "sendTo": "Send to", + "to": "to", + "pay": "Pay", + "requesting": "is requesting", + "sentInvoiceTo": "Sent invoice to", + "sentRequestTo": "Request sent!", + "pleasePay": "Please pay", + "day": "Day", + "week": "Week", + "month": "Month", + "all": "All", + "export": "Export", + "invoice": "Invoice", + "readyToPay": "is ready to pay", + "describeOrder": "Use this field to describe your order", + "requestAnInvoice": "Request Invoice", + "submit": "Submit", + "isRequesting": "is requesting", + "invoiceFrom": "Invoice from", + "awaiting": "Awaiting", + "tapAnywhere": "Tap anywhere to continue", + "from": "from", + "redeem": "Redeem", + "redeemed": "Redeemed", + "redeemedBy": "Redeemed by", + "sendMessage": "Write a message..." + } +} diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index b87ac355..6143955b 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -2,7 +2,7 @@ import { SvelteToast } from '@zerodevx/svelte-toast'; import { onDestroy, onMount } from 'svelte'; import { close, connect, send } from '$lib/socket'; - import { last, invoice, request, passwordPrompt } from '$lib/store'; + import { last, invoice, request, passwordPrompt, pin } from '$lib/store'; import { page } from '$app/stores'; import { browser } from '$app/environment'; import { goto } from '$app/navigation'; @@ -14,8 +14,12 @@ export let data; - let { subject } = $page.data; - let { rate, user, token, rates } = data; + let { rate, user, subject, token, rates } = data; + + $: update(data); + let update = (data) => { + ({ rate, user, subject, token, rates } = data); + }; onMount(() => { let localStorageLocale = localStorage.getItem(localeLocalStorageKey); @@ -25,27 +29,42 @@ if (lng) localStorage.setItem(localeLocalStorageKey, lng); }); - browser && checkSocket(); + if (browser) { + checkSocket(); + expirePin(); + } }); $: browser && connect(token); let lost, - timer, + checkTimer, + expireTimer, counter = 0; let checkSocket = () => { counter++; - lost = Date.now() - $last > 15000; + lost = Date.now() - $last > 30000; if (lost) connect(token); if (counter > 5) { - send('heartbeat'); + send('heartbeat', token); counter = 0; } - timer = setTimeout(checkSocket, 1000); + + checkTimer = setTimeout(checkSocket, 1000); + }; + + let expirePin = () => { + $pin = null; + expireTimer = setTimeout(expirePin, 300000); }; - onDestroy(() => browser && clearTimeout(timer)); + onDestroy(() => { + if (browser) { + clearTimeout(checkTimer); + clearTimeout(expireTimer); + } + }); </script> {#if browser && $passwordPrompt} @@ -69,12 +88,6 @@ <SvelteToast options={{ reversed: true, intro: { y: 192 } }} /> -{#if lost} - <div class="fixed bottom-12 right-12 text-red-600 bg-white z-50 px-4 py-2 rounded-full border"> - Lost connection to server, try refreshing - </div> -{/if} - <main data-sveltekit-prefetch class="pb-20"> <slot /> </main> diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte index 1b212abe..2bd465a7 100644 --- a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte +++ b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte @@ -33,6 +33,8 @@ $: form?.success && success('Settings saved!'); + $: form?.message && fail(form.message); + $: if (form?.message?.startsWith('Pin')) { fail('Wrong pin, try again'); $pin = ''; diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index 9e61cbd6..1da3f872 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -113,7 +113,7 @@ </div> {/if} - {#if user.username.toLowerCase() === 'laughingbean'} + {#if ['laughingbean', 'burnabyartigiano', 'milanowestend'].includes(user.username.toLowerCase()) } <button class="text-sm md:text-lg rounded-full border py-2 px-4 hover:opacity-80 min-w-[72px] bg-black text-white" on:click={print}>Print Receipt</button diff --git a/src/routes/(app)/register/+page.server.js b/src/routes/(app)/register/+page.server.js index e71b2a60..8a8ca81c 100644 --- a/src/routes/(app)/register/+page.server.js +++ b/src/routes/(app)/register/+page.server.js @@ -16,7 +16,7 @@ export const actions = { if (loginRedirect === 'undefined') loginRedirect = undefined; try { - await post('/register', { user }); + await post('/register', { user }, { "cf-connecting-ip": request.headers.get('cf-connecting-ip') }); } catch (e) { if (e.message.includes('taken')) error = e.message; } diff --git a/src/routes/(app)/send/+layout.svelte b/src/routes/(app)/send/+layout.svelte index 6192cd40..47c11f1c 100644 --- a/src/routes/(app)/send/+layout.svelte +++ b/src/routes/(app)/send/+layout.svelte @@ -1,10 +1,7 @@ <script> - import { browser } from '$app/environment'; import { goto } from '$app/navigation'; import { Pin } from '$comp'; import { pin } from '$lib/store'; - import { onMount } from 'svelte'; - import { success, fail, post } from '$lib/utils'; export let data; diff --git a/src/routes/(app)/send/[...text]/+page.server.js b/src/routes/(app)/send/[...text]/+page.server.js index 9c7d4185..513fa11e 100644 --- a/src/routes/(app)/send/[...text]/+page.server.js +++ b/src/routes/(app)/send/[...text]/+page.server.js @@ -2,10 +2,13 @@ import { validate } from 'bitcoin-address-validation'; import bip21 from 'bip21'; import { auth, get, post } from '$lib/utils'; import { fail, redirect } from '@sveltejs/kit'; +import { PUBLIC_DOMAIN } from '$env/static/public'; let parse = async (t, host) => { if (!t) return; + if (t.startsWith('http')) throw redirect(307, t); + let amount, user, id; t = t.trim(); @@ -15,6 +18,7 @@ let parse = async (t, host) => { options: { amount } } = bip21.decode(t)); + if (t.endsWith(`@${PUBLIC_DOMAIN}`)) t = t.split('@')[0]; if (t.includes('@') && t.includes('.')) { try { t = await get(`/encode?address=${t}`); diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 2db2854a..3a5a54f3 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -15,8 +15,9 @@ import { onMount } from 'svelte'; export let data; - let { user } = data; - let { locations } = data; + let { locations, user } = data; + let update = (data) => ({ locations, user } = data); + $: update(data); let howItWorks; let faq; |
