Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Welcome screen #275

Merged
merged 21 commits into from
Dec 18, 2024
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,49 @@ npm run build
### Customize the configuration

See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js).

### Reverse proxy

For Quasar Vue Router with history mode, add this fallback URL to allow refreshes: https://router.vuejs.org/guide/essentials/history-mode.html#HTML5-Mode

More info: https://stackoverflow.com/questions/36399319/vue-router-return-404-when-revisit-to-the-url

`Caddyfile`:

```
# CORS snippet by https://kalnytskyi.com/posts/setup-cors-caddy-2/
(cors) {
@cors_preflight method OPTIONS
@cors header Origin {args.0}

handle @cors_preflight {
header Access-Control-Allow-Origin "{args.0}"
header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
header Access-Control-Allow-Headers "Content-Type"
header Access-Control-Max-Age "3600"
respond "" 204
}

handle @cors {
header Access-Control-Allow-Origin "{args.0}"
header Access-Control-Expose-Headers "Link"
}
}
host.com {
import cors *
encode gzip

header /service-worker.js {
Service-Worker-Allowed "/"
Cache-Control "no-cache"
}

# SPA root
root * /usr/share/caddy/cashu.me/

# quasar vue router fallback history mode
try_files {path} /index.html

file_server
}
```
117 changes: 117 additions & 0 deletions src/components/AndroidPWAPrompt.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!-- src/components/AndroidPWAPrompt.vue -->
<template>
<transition appear enter-active-class="animated fadeInDown">
<div
v-if="showAndroidPWAPrompt"
class="pwa-prompt android-pwa-prompt q-pa-md text-center"
>
<div class="pwa-prompt-content">
<span>
Tap <q-icon name="more_vert" size="sm" /> and
<strong>Add to Home screen</strong>
</span>
<q-btn
flat
icon="close"
@click="closePrompt"
size="sm"
class="close-btn q-px-sm"
/>
</div>

<div class="pwa-prompt-arrow"></div>
</div>
</transition>
</template>

<script>
import { defineComponent } from "vue";

export default defineComponent({
name: "AndroidPWAPrompt",
data() {
return {
showAndroidPWAPromptLocal:
localStorage.getItem("cashu.ui.showAndroidPWAPrompt") != "seen",
showAndroidPWAPrompt: false,
};
},
mounted() {
if (
this.showAndroidPWAPromptLocal &&
this.isChromeOnAndroid() &&
!this.isInStandaloneMode()
) {
this.showAndroidPWAPrompt = true;
}
},
methods: {
closePrompt() {
localStorage.setItem("cashu.ui.showAndroidPWAPrompt", "seen");
this.showAndroidPWAPrompt = false;
},
isChromeOnAndroid() {
const userAgent = navigator.userAgent.toLowerCase();
const isAndroid = /android/.test(userAgent);
const isChrome =
/chrome/.test(userAgent) && !/edge|edg|opr|opera/.test(userAgent);
return isAndroid && isChrome;
},
isInStandaloneMode() {
return window.matchMedia("(display-mode: standalone)").matches;
},
},
});
</script>

<style scoped>
@keyframes moveUpDown {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}

.pwa-prompt {
position: fixed;
top: 20px;
right: 20px;
margin: 0 auto;
z-index: 9999;
text-align: center;
display: flex;
flex-direction: column; /* Add this line */
align-items: center; /* Add this line */
justify-content: center;
animation: moveUpDown 1s infinite; /* Add this line for animation */
}

.pwa-prompt-content {
display: inline-flex;
align-items: center;
background-color: black;
padding: 10px;
border: 1px solid #ccc;
border-radius: 8px;
}

.pwa-prompt-content q-icon {
margin-right: 5px;
}

.pwa-prompt-arrow {
position: relative;
width: 0;
height: 0;
bottom: 60px;
left: 45%;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid white;
text-align: center;
margin: 0 auto;
}
</style>
8 changes: 8 additions & 0 deletions src/components/BalanceView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,11 @@ export default defineComponent({
},
});
</script>
<style scoped>
.animated.pulse {
animation-duration: 0.5s;
}
.animated.fadeInDown {
animation-duration: 0.3s;
}
</style>
20 changes: 13 additions & 7 deletions src/components/MainHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
color="primary"
aria-label="Menu"
@click="toggleLeftDrawer"
:disable="uiStore.globalMutexLock"
/>
<q-toolbar-title></q-toolbar-title>
<transition
Expand Down Expand Up @@ -64,6 +65,7 @@
:color="countdown > 0 ? 'negative' : 'primary'"
aria-label="Refresh"
@click="reload"
:disable="uiStore.globalMutexLock && countdown === 0"
>
</q-btn>
</q-toolbar>
Expand All @@ -81,6 +83,16 @@
<q-item-label caption>Wallet configuration</q-item-label>
</q-item-section>
</q-item>
<q-item-label header>Terms </q-item-label>
<q-item clickable to="/terms">
<q-item-section avatar>
<q-icon name="gavel" />
</q-item-section>
<q-item-section>
<q-item-label>Terms</q-item-label>
<q-item-label caption>Terms of Service</q-item-label>
</q-item-section>
</q-item>
<q-item-label header>Links </q-item-label>
<EssentialLink
v-for="link in essentialLinks"
Expand Down Expand Up @@ -121,15 +133,9 @@ const linksList = [
icon: "rss_feed",
link: "https://twitter.com/CashuBTC",
},
{
title: "Terms",
caption: "Terms of service",
icon: "info_i",
link: "https://docs.cashu.space/contribute",
},
{
title: "Donate",
caption: "Support Cashu development",
caption: "Support Cashu",
icon: "favorite",
link: "https://docs.cashu.space/contribute",
},
Expand Down
25 changes: 22 additions & 3 deletions src/components/NoMintWarnBanner.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<template>
<div class="q-ma-lg q-pa-md" style="border: 2px solid; border-radius: 10px">
<q-card class="q-ma-lg bg-dark q-pa-md">
<q-card-section>
<div class="row items-center justify-center">
<q-icon class="q-pb-md" name="account_balance" size="50px" />
<q-icon
color="primary"
class="q-pb-md"
name="account_balance"
size="50px"
/>
</div>
<div class="row items-center justify-center">
<div class="text-h6">Join a mint</div>
Expand Down Expand Up @@ -33,7 +38,7 @@
/>
</div>
</q-card-section>
</div>
</q-card>
</template>
<script>
import { defineComponent, ref } from "vue";
Expand Down Expand Up @@ -89,3 +94,17 @@ export default defineComponent({
},
});
</script>
<style scoped>
.q-dialog__inner {
height: 100%;
width: 100%;
margin: 0; /* Align dialog to cover the entire viewport */
}

.q-card {
border-radius: 20px;
display: flex;
flex-direction: column;
border: 2px solid var(--q-primary);
}
</style>
43 changes: 37 additions & 6 deletions src/components/PaymentRequestDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@
<div class="row justify-center">
<q-card-section class="q-pa-sm">
<div class="row justify-center q-pt-sm">
<q-chip outline class="q-pa-md q-py-md" style="height: 36px">
<q-icon name="account_balance" size="xs" class="q-mr-xs" />
{{ getShortUrl(activeMintUrl) }}
<q-chip
outline
clickable
class="q-pa-md q-py-md"
style="height: 36px"
@click="setActiveMintUrl"
>
<q-icon name="account_balance" size="xs" class="q-mr-sm" />
{{ getShortUrl(chosenMintUrl) }}
</q-chip>
<div @click="toggleUnit" class="q-mt-xs q-ml-sm">
<ToggleUnit class="q-py-none" color="white" />
Expand Down Expand Up @@ -118,6 +124,8 @@ export default defineComponent({
amountInputValue: "",
amountLabelDefault: "Add amount",
amountLabel: "Add amount",
chosenMintUrl: "Any mint",
memo: "",
};
},
computed: {
Expand All @@ -134,14 +142,33 @@ export default defineComponent({
toggleUnit() {
this.paymentRequestAmount = undefined;
this.amountLabel = this.amountLabelDefault;
this.newPaymentRequest(this.paymentRequestAmount);
this.newPaymentRequest(
this.paymentRequestAmount,
this.memo,
this.chosenMintUrl
);
},
newRequest() {
this.newPaymentRequest(this.paymentRequestAmount);
this.newPaymentRequest(
this.paymentRequestAmount,
this.memo,
this.chosenMintUrl
);
},
getShortUrl(url) {
return getShortUrl(url);
},
setActiveMintUrl() {
if (this.activeMintUrl == this.chosenMintUrl) {
return;
}
this.chosenMintUrl = this.activeMintUrl;
this.newPaymentRequest(
this.paymentRequestAmount,
this.memo,
this.chosenMintUrl
);
},
startEditingAmount() {
this.isEditingAmount = true;
this.$nextTick(() => {
Expand All @@ -162,7 +189,11 @@ export default defineComponent({
this.activeUnit
);
}
this.newPaymentRequest(this.paymentRequestAmount);
this.newPaymentRequest(
this.paymentRequestAmount,
this.memo,
this.chosenMintUrl
);
this.isEditingAmount = false;
this.amountInputValue = "";
},
Expand Down
9 changes: 8 additions & 1 deletion src/components/ReceiveTokenDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
label="Paste Cashu token"
type="textarea"
autofocus
class="q-mb-lg"
class="q-mb-lg cashub-nowrap"
@keyup.enter="receiveIfDecodes"
>
<template v-if="receiveData.tokensBase64" v-slot:append>
Expand Down Expand Up @@ -327,4 +327,11 @@ export default defineComponent({
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
}

.cashub-nowrap {
word-break: break-all;
-webkit-hyphens: none;
-moz-hyphens: none;
hyphens: none;
}
</style>
Loading
Loading