Wall of People Groups: Share works in Social mode, the loading screen stays inside the wall, and the orientation switch shows only where it does something
Share opens the phone's share sheet for the group's prayer page, or copies the link and says Copied!. The loading overlay was position:fixed and covered an embedding page; it now sits inside the wall like the offline notice. Landscape / portrait arranges the Social board only: in Bless mode the wall is the poster.
This commit is contained in:
parent
2473ce5d01
commit
9d3040867f
2 changed files with 47 additions and 6 deletions
|
|
@ -3,7 +3,8 @@
|
|||
<div class="wall-header">
|
||||
<h1>{{ mode === 'bless' ? $t('wall.blessBanner') : $t('wall.title') }}</h1>
|
||||
<div class="wall-controls">
|
||||
<button @click="toggleOrientation" class="control-btn orientation-btn">
|
||||
<!-- Landscape / portrait arranges the SOCIAL board; in Bless mode the wall is the poster itself. -->
|
||||
<button v-if="mode === 'social'" @click="toggleOrientation" class="control-btn orientation-btn">
|
||||
<span class="btn-label">{{ isLandscape ? $t('wall.toPortrait') : $t('wall.toLandscape') }}</span>
|
||||
<span class="current-mode">{{ isLandscape ? $t('wall.currentLandscape') : $t('wall.currentPortrait') }}</span>
|
||||
</button>
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
</div>
|
||||
|
||||
<div ref="canvas" class="wall-canvas"></div>
|
||||
<div v-if="toast" class="wall-toast" role="status">{{ toast }}</div>
|
||||
|
||||
<div v-if="loading" class="loading-overlay">
|
||||
<div class="spinner"></div>
|
||||
|
|
@ -47,7 +49,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { WallCanvas } from '../wallCanvas.js'
|
||||
import { WallCanvas, groupLink } from '../wallCanvas.js'
|
||||
import { buildBlessPosterHtml, screenPoster, PRESETS, DEFAULT_PRESET } from '../blessPoster.js'
|
||||
import { openPrintFrame } from '@map/composables/printInPlace.js'
|
||||
// Wall of People Groups: a zoomable canvas wall (wallCanvas.js), Bless or Social cards, and the poster print.
|
||||
|
|
@ -62,7 +64,8 @@ export default {
|
|||
// Each label is isolated left to right (U+2066 … U+2069): "5 × 8 ft · 3×" would otherwise be reordered
|
||||
// by an RTL page into "×ft · 3 8 × 5" (an <option> cannot hold a <bdi>).
|
||||
posterPresets: Object.entries(PRESETS).map(([id, p]) => ({ id, label: '\u2066' + p.label + (p.sheets > 1 ? ' · ' + p.sheets + '×' : '') + '\u2069' })),
|
||||
printing: false, // the HD poster print is loading photos (drives the button's busy state)
|
||||
printing: false,
|
||||
toast: '', // a short status line over the wall (e.g. "Copied!"), cleared by flash() // the HD poster print is loading photos (drives the button's busy state)
|
||||
cardWidth: 50,
|
||||
cardHeight: 70,
|
||||
cardSpacing: 8, // Increased horizontal spacing (was 2)
|
||||
|
|
@ -130,7 +133,7 @@ export default {
|
|||
prayCount: (d) => Number(d.peoplePraying || 0) + (this.$store?.prayers?.[d.ID] || 0),
|
||||
onPray: (d) => this.openPrayerDialog(d),
|
||||
onComments: (d) => this.openComments(d),
|
||||
onShare: () => alert(this.$t('wall.shareSoon')),
|
||||
onShare: (d) => this.shareGroup(d),
|
||||
});
|
||||
this._wc.setMode(this.mode);
|
||||
},
|
||||
|
|
@ -186,6 +189,28 @@ export default {
|
|||
dir: /^(ar|he|fa|ur)/.test(String(this.$i18n?.locale || '')) ? 'rtl' : 'ltr',
|
||||
};
|
||||
},
|
||||
// SHARE (Social mode): the group's prayer page (groupLink: pray.doxa.life, else Joshua Project).
|
||||
// The phone's share sheet where there is one; otherwise the link is copied, and "Copied!" says so.
|
||||
// If the clipboard is refused (an http page, a denied permission), the page opens instead.
|
||||
async shareGroup(g) {
|
||||
const url = groupLink(g);
|
||||
if (!url) return;
|
||||
const title = g.name || g.post_title || '';
|
||||
if (typeof navigator !== 'undefined' && navigator.share) {
|
||||
try { await navigator.share({ title, url }); return; }
|
||||
catch (e) { if (e && e.name === 'AbortError') return; }
|
||||
}
|
||||
try { await navigator.clipboard.writeText(url); this.flash(this.$t('messages.copied')); }
|
||||
catch (_) { window.open(url, '_blank', 'noopener,noreferrer'); }
|
||||
},
|
||||
// Show a status line for a moment. Cleared by IDENTITY (the token it set), never by comparing text,
|
||||
// so a translated message clears just the same.
|
||||
flash(msg, ms = 2000) {
|
||||
const token = {};
|
||||
this._toastToken = token;
|
||||
this.toast = msg;
|
||||
setTimeout(() => { if (this._toastToken === token) this.toast = ''; }, ms);
|
||||
},
|
||||
setMode(m) {
|
||||
if (this.mode === m) return;
|
||||
this.mode = m;
|
||||
|
|
|
|||
|
|
@ -151,9 +151,10 @@ body {
|
|||
.wall-offline-title { font-weight: 600; font-size: 16px; margin-bottom: 6px; }
|
||||
.wall-offline p { margin: 0 0 12px; }
|
||||
|
||||
/* Loading Overlay */
|
||||
/* Loading Overlay: inside the wall like the offline notice (position:fixed covered an embedding
|
||||
partner's whole page while the groups loaded). */
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
|
@ -181,6 +182,21 @@ body {
|
|||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* A short status line over the wall ("Copied!"). */
|
||||
.wall-toast {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 24px;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(38, 38, 38, 0.92);
|
||||
color: #fff;
|
||||
padding: 8px 16px;
|
||||
border-radius: 999px;
|
||||
font-size: 14px;
|
||||
z-index: 30;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Comments Dialog */
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
|
|
|
|||
Loading…
Reference in a new issue