Change settings button position
This commit is contained in:
1 parent
78c1d8e844
commit
8db3b3d363
12 files changed
+240
-48
No files matched your search
@@ -47,7 +47,7 @@
|
||||
"loading": "Turning pages…",
|
||||
"today": "Today",
|
||||
"go_to_writing": "Back to today's page",
|
||||
"empty_entry": "Blank page",
|
||||
"new_entry": "Start a new page",
|
||||
"earlier": "Earlier entries",
|
||||
"later": "Later entries"
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"loading": "On tourne les pages…",
|
||||
"today": "Aujourd'hui",
|
||||
"go_to_writing": "Revenir à la page du jour",
|
||||
"empty_entry": "Page blanche",
|
||||
"new_entry": "Commencer une nouvelle page",
|
||||
"earlier": "Entrées précédentes",
|
||||
"later": "Entrées suivantes"
|
||||
},
|
||||
|
||||
+51
-2
@@ -35,6 +35,7 @@ export default {
|
||||
bCalendarOpen: false,
|
||||
bSettingsOpen: false,
|
||||
bMenuOpen: false,
|
||||
bSigningOut: false,
|
||||
bRailOpen: false,
|
||||
iCurrentId: 0,
|
||||
sCurrentDay: '',
|
||||
@@ -127,13 +128,51 @@ export default {
|
||||
this.$refs.book?.goToWriting();
|
||||
},
|
||||
|
||||
/**
|
||||
* The + at the end of the rail: seal the page being written and turn to
|
||||
* a fresh one. Landing there should mean you can simply write, the same
|
||||
* way opening the book does.
|
||||
*/
|
||||
async onNewEntry() {
|
||||
this.bRailOpen = false;
|
||||
|
||||
try {
|
||||
await this.journal.startNewEntry();
|
||||
this.$nextTick(() => this.$refs.book?.goToWriting());
|
||||
}
|
||||
catch(oError) {
|
||||
this.notify(oError.desc_lang_text || oError.message, true);
|
||||
}
|
||||
},
|
||||
|
||||
/* Account */
|
||||
|
||||
onSignedIn(asUser) {
|
||||
Object.assign(this.user, asUser);
|
||||
},
|
||||
|
||||
async onSignedOut() {
|
||||
/**
|
||||
* The logout call is what ends the session; the local reset only
|
||||
* follows it, so a failed call leaves the reader where they were.
|
||||
*/
|
||||
async signOut() {
|
||||
if(this.bSigningOut) return;
|
||||
|
||||
this.bSigningOut = true;
|
||||
|
||||
try {
|
||||
await this.api.post('logout');
|
||||
this.clearSession();
|
||||
}
|
||||
catch(oError) {
|
||||
this.notify(oError.desc_lang_text || oError.message || this.lang.get('error.unexpected'), true);
|
||||
}
|
||||
finally {
|
||||
this.bSigningOut = false;
|
||||
}
|
||||
},
|
||||
|
||||
clearSession() {
|
||||
this.bSettingsOpen = false;
|
||||
this.bMenuOpen = false;
|
||||
|
||||
@@ -259,6 +298,16 @@ export default {
|
||||
<appIcon icon="settings" />
|
||||
<span>{{ lang.get('account.settings') }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="account-menu__item account-menu__item--bad"
|
||||
:disabled="bSigningOut"
|
||||
@click="signOut"
|
||||
>
|
||||
<appIcon icon="signOut" />
|
||||
<span>{{ lang.get('account.sign_out') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -287,6 +336,7 @@ export default {
|
||||
:loading="journal.loading"
|
||||
@pick="onPickBookmark"
|
||||
@load-older="onLoadOlder"
|
||||
@new="onNewEntry"
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
@@ -304,7 +354,6 @@ export default {
|
||||
<settingsPanel
|
||||
v-if="bSettingsOpen"
|
||||
@close="bSettingsOpen = false"
|
||||
@signed-out="onSignedOut"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -40,6 +40,10 @@ const RAIL_REACH = 3;
|
||||
* Each is stamped with the date and time the entry was started, in the timezone
|
||||
* it was written in - so a book kept across a move still reads as the local
|
||||
* time of each moment. Clicking one turns the book to that page.
|
||||
*
|
||||
* A page nothing has been written on is not one of them: an empty tab marks
|
||||
* nothing, and a book of them would be a rail of blanks. The + at the end of
|
||||
* the rail stands there instead, and starts the page it would have marked.
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
@@ -54,15 +58,18 @@ export default {
|
||||
hasOlder: {type: Boolean, default: false},
|
||||
loading: {type: Boolean, default: false}
|
||||
},
|
||||
emits: ['pick', 'load-older'],
|
||||
emits: ['pick', 'load-older', 'new'],
|
||||
inject: ['lang'],
|
||||
computed: {
|
||||
tabs() {
|
||||
return this.bookmarks.map((oBookmark) => ({
|
||||
//A bookmark is a page with something on it. The one page that can be
|
||||
//empty is the one being written, and it gets its tab with its first
|
||||
//words - closed entries are never blank, the book discards those.
|
||||
return this.bookmarks.filter((oBookmark) => (oBookmark.preview || '') !== '').map((oBookmark) => ({
|
||||
id: oBookmark.id,
|
||||
date: formatShortDate(oBookmark.time, oBookmark.timezone, this.lang.locale),
|
||||
time: formatTime(oBookmark.time, oBookmark.timezone, this.lang.locale),
|
||||
preview: oBookmark.preview || this.lang.get('book.empty_entry'),
|
||||
preview: oBookmark.preview,
|
||||
open: (oBookmark.status === 'open'),
|
||||
dye: dyeForDay(getDayKey(oBookmark.time, oBookmark.timezone))
|
||||
}));
|
||||
@@ -89,6 +96,16 @@ export default {
|
||||
},
|
||||
hasAfter() {
|
||||
return (this.shown.length > 0) && (this.shown.at(-1).id !== this.tabs.at(-1)?.id);
|
||||
},
|
||||
/**
|
||||
* Whether the book is open at a page still to be written on.
|
||||
*
|
||||
* That page has no tab, so the + is what marks it - and the rail would
|
||||
* otherwise show nothing at all as the place you are reading.
|
||||
*/
|
||||
onBlankPage() {
|
||||
const oOpen = this.bookmarks.find((oBookmark) => oBookmark.id === this.openId);
|
||||
return (this.currentId === this.openId) && (oOpen !== undefined) && ((oOpen.preview || '') === '');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -162,6 +179,19 @@ export default {
|
||||
</span>
|
||||
<span class="rail__preview">{{ oTab.preview }}</span>
|
||||
</button>
|
||||
|
||||
<!-- Straight after the last tab: the page that has not been started
|
||||
yet, where its own tab will be once there is something on it. -->
|
||||
<button
|
||||
type="button"
|
||||
class="rail__new"
|
||||
:class="onBlankPage ? 'rail__new--current' : null"
|
||||
:title="lang.get('book.new_entry')"
|
||||
:aria-label="lang.get('book.new_entry')"
|
||||
@click="$emit('new')"
|
||||
>
|
||||
<appIcon icon="plus" size="1.1em" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
||||
@@ -13,7 +13,7 @@ export default {
|
||||
components: {
|
||||
appIcon
|
||||
},
|
||||
emits: ['close', 'signed-out'],
|
||||
emits: ['close'],
|
||||
inject: ['api', 'consts', 'lang', 'user'],
|
||||
data() {
|
||||
return {
|
||||
@@ -90,19 +90,6 @@ export default {
|
||||
saveName() {
|
||||
const sName = this.sName.trim();
|
||||
if((sName !== '') && (sName !== this.user.name)) this.set('name', sName);
|
||||
},
|
||||
async signOut() {
|
||||
this.bBusy = true;
|
||||
try {
|
||||
await this.api.post('logout');
|
||||
this.$emit('signed-out');
|
||||
}
|
||||
catch(oError) {
|
||||
this.sError = oError.desc_lang_text || oError.message;
|
||||
}
|
||||
finally {
|
||||
this.bBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -188,9 +175,6 @@ export default {
|
||||
<appIcon icon="check" />
|
||||
<span>{{ lang.get('action.close') }}</span>
|
||||
</button>
|
||||
<button type="button" class="text-button text-button--bad" :disabled="bBusy" @click="signOut">
|
||||
<span>{{ lang.get('account.sign_out') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,16 +38,10 @@ const asIcons = {
|
||||
'M12 11.6a3.6 3.6 0 1 0 0-7.2 3.6 3.6 0 0 0 0 7.2z',
|
||||
'M4.8 20c.6-3.7 3.5-5.8 7.2-5.8s6.6 2.1 7.2 5.8'
|
||||
],
|
||||
//A cog: six teeth around a hub
|
||||
settings: [
|
||||
'M12 15.2a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4z',
|
||||
'M12 3v2.3',
|
||||
'M12 18.7V21',
|
||||
'M3 12h2.3',
|
||||
'M18.7 12H21',
|
||||
'M5.6 5.6l1.7 1.7',
|
||||
'M16.7 16.7l1.7 1.7',
|
||||
'M18.4 5.6l-1.7 1.7',
|
||||
'M7.3 16.7l-1.7 1.7'
|
||||
'M10.3 6L10.4 3.1h3.2L13.7 6a6.2 6.2 0 0 1 2.6 1.5l2.6-1.3 1.6 2.7-2.5 1.6a6.2 6.2 0 0 1 0 3l2.5 1.6-1.6 2.7-2.6-1.3a6.2 6.2 0 0 1-2.6 1.5l-.1 2.9h-3.2L10.3 18a6.2 6.2 0 0 1-2.6-1.5l-2.6 1.3-1.6-2.7 2.5-1.6a6.2 6.2 0 0 1 0-3L3.5 8.9l1.6-2.7 2.6 1.3A6.2 6.2 0 0 1 10.3 6z',
|
||||
'M12 14.8a2.8 2.8 0 1 0 0-5.6 2.8 2.8 0 0 0 0 5.6z'
|
||||
],
|
||||
signOut: [
|
||||
'M14.4 8V5.2H5.6v13.6h8.8V16',
|
||||
@@ -61,6 +55,8 @@ const asIcons = {
|
||||
'M10.5 10.9v5.7',
|
||||
'M13.5 10.9v5.7'
|
||||
],
|
||||
//A blank page waiting to be started
|
||||
plus: ['M12 5.6v12.8', 'M5.6 12h12.8'],
|
||||
close: ['M6.6 6.6l10.8 10.8', 'M17.4 6.6 6.6 17.4'],
|
||||
check: ['M5.6 12.7l4.2 4.2 8.6-9.6'],
|
||||
alert: [
|
||||
|
||||
@@ -172,6 +172,33 @@ export default class Journal {
|
||||
return oEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a page of one's own, rather than writing on in the last one.
|
||||
*
|
||||
* A page nothing has been written on is already that page, so it is handed
|
||||
* straight back - it is only a page with writing on it that has to be sealed
|
||||
* first, which is what makes the next one a new entry and not the same
|
||||
* thought carried on.
|
||||
*/
|
||||
async startNewEntry() {
|
||||
const oEntry = this.openEntry;
|
||||
if(oEntry && (oEntry.content.trim() === '')) return oEntry;
|
||||
|
||||
//The close carries the content itself, but the save state goes with it -
|
||||
//flushing here is what keeps the indicator from sitting on "unsaved"
|
||||
//about a page that has already been sealed.
|
||||
if(this.isDirty) await this.save();
|
||||
|
||||
await this.closeEntry();
|
||||
|
||||
//A new page goes at the end of the book, so the loaded window has to be
|
||||
//the end of the book before one can be appended to it - reading back in
|
||||
//the journal would otherwise slot it into the middle of the flow.
|
||||
if(this.hasNewer) await this.load();
|
||||
|
||||
return this.startWriting();
|
||||
}
|
||||
|
||||
write(sContent) {
|
||||
const oEntry = this.openEntry;
|
||||
if(!oEntry) return;
|
||||
|
||||
@@ -206,3 +206,13 @@
|
||||
background-color: color.$paper-shade;
|
||||
}
|
||||
}
|
||||
|
||||
.account-menu__item--bad {
|
||||
color: color.$bad;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: color.$bad;
|
||||
background-color: rgba(155, 70, 49, 0.09);
|
||||
}
|
||||
}
|
||||
+17
-5
@@ -170,28 +170,40 @@
|
||||
border-right: 1px solid color.$rule-margin;
|
||||
}
|
||||
|
||||
/* Where an entry begins, the margin says when it was written */
|
||||
/* Where an entry begins, the margin says when it was written.
|
||||
*
|
||||
* Sized off the ruled line like the writing it annotates, so it follows the
|
||||
* hand in use instead of holding one fixed size across six of them - a stamp
|
||||
* in a wide hand at a fixed size is wider than the column it sits in. Both
|
||||
* spans are led at half a rule, so the usual date-over-time comes to exactly
|
||||
* one ruled line and a date long enough to wrap still lands on the book's
|
||||
* rhythm rather than between it. */
|
||||
.page__stamp {
|
||||
--stamp-size: calc(var(--book-line) * #{var.$hand-scale} * 0.5);
|
||||
|
||||
position: absolute;
|
||||
right: 0.7rem;
|
||||
width: calc(100% - 0.7rem);
|
||||
text-align: right;
|
||||
font-family: var.$font-hand;
|
||||
line-height: 1.05;
|
||||
line-height: calc(var(--book-line) / 2);
|
||||
color: color.$ink-soft;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.page__stamp-date {
|
||||
display: block;
|
||||
font-size: 1.05rem;
|
||||
font-size: var(--stamp-size);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
|
||||
//A written-out month in a wide hand, or a locale that spells the date out
|
||||
//at length, wraps inside the margin instead of spilling over the page.
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.page__stamp-time {
|
||||
display: block;
|
||||
font-size: 0.95rem;
|
||||
font-size: calc(var(--stamp-size) * 0.9);
|
||||
color: color.$ink-faint;
|
||||
}
|
||||
|
||||
|
||||
+40
-9
@@ -77,23 +77,19 @@
|
||||
}
|
||||
|
||||
.page__margin {
|
||||
flex-basis: 3.1rem;
|
||||
flex-basis: 4.1rem;
|
||||
padding-right: 0.4rem;
|
||||
}
|
||||
|
||||
//A phone gives the margin less room, so the stamp is written smaller in it
|
||||
//rather than wider than it.
|
||||
.page__stamp {
|
||||
--stamp-size: calc(var(--book-line) * #{var.$hand-scale} * 0.42);
|
||||
|
||||
right: 0.4rem;
|
||||
width: calc(100% - 0.4rem);
|
||||
}
|
||||
|
||||
.page__stamp-date {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.page__stamp-time {
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.page__column,
|
||||
.page__measure,
|
||||
.page__input,
|
||||
@@ -175,6 +171,41 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* In the drawer there is no page block for a tab to come out from under, so
|
||||
* the + is a card like the tabs are - drawn in the light ink the cover asks
|
||||
* for rather than in paper tones, and it stays put instead of sliding out. */
|
||||
.rail__new {
|
||||
width: 100%;
|
||||
min-height: 2.4rem;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
color: rgba(254, 244, 225, 0.6);
|
||||
background-color: rgba(254, 244, 225, 0.06);
|
||||
border: 1px dashed rgba(254, 244, 225, 0.3);
|
||||
border-radius: var.$block-radius;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
transform: none;
|
||||
color: color.$paper;
|
||||
background-color: rgba(254, 244, 225, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
.rail__new--current {
|
||||
transform: none;
|
||||
color: color.$paper;
|
||||
background-color: rgba(254, 244, 225, 0.14);
|
||||
border-style: solid;
|
||||
border-color: rgba(254, 244, 225, 0.35);
|
||||
box-shadow: inset -0.2rem 0 0 color.$ribbon;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar {
|
||||
width: min(19rem, calc(100vw - 1.5rem));
|
||||
}
|
||||
|
||||
@@ -159,6 +159,58 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* The page nobody has written on yet.
|
||||
*
|
||||
* Shaped like a tab, because that is what it becomes the moment something is
|
||||
* written on it - but a short one, drawn in outline: there is no date to stamp
|
||||
* on it and no day for it to take a dye from. It stands in the stack directly
|
||||
* after the last tab, which is where its own tab will be.
|
||||
*/
|
||||
.rail__new {
|
||||
flex: 0 0 auto;
|
||||
align-self: flex-start;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 4.75rem;
|
||||
min-height: 1.9rem;
|
||||
//The list's own gap sets it off from the last tab
|
||||
margin-left: calc(-1 * var.$tab-tuck);
|
||||
padding-left: var.$tab-tuck;
|
||||
|
||||
color: color.$ink-faint;
|
||||
background-color: rgba(251, 241, 220, 0.5);
|
||||
//No left edge: like a tab, it comes out from under the page block
|
||||
border: 1px dashed color.$paper-deep;
|
||||
border-left: 0;
|
||||
border-radius: 0 var.$block-radius var.$block-radius 0;
|
||||
|
||||
transition: transform var.$trans-mid ease-out, background-color var.$trans-quick, color var.$trans-quick;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
transform: translateX(0.45rem);
|
||||
background-color: color.$paper;
|
||||
color: color.$ink-soft;
|
||||
}
|
||||
}
|
||||
|
||||
/* The book is open at that page, so the + is doing a bookmark's job - and wears
|
||||
* the same ribbon the tab of the page being written on would. */
|
||||
.rail__new--current {
|
||||
transform: translateX(0.3rem);
|
||||
color: color.$ink-soft;
|
||||
background-color: color.$paper;
|
||||
border-style: solid;
|
||||
border-color: color.$paper-edge;
|
||||
box-shadow: 0.12rem 0.15rem 0.5rem rgba(90, 54, 31, 0.22), inset -0.2rem 0 0 color.$ribbon;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
transform: translateX(0.65rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* The rail shows a few tabs either side of where the reading is. These two
|
||||
* say the book carries on past them, and walk the window along. */
|
||||
.rail__more {
|
||||
|
||||
@@ -14,7 +14,8 @@ $block-spacing: 1rem;
|
||||
$block-radius: 3px;
|
||||
|
||||
//The book
|
||||
$page-margin-width: 4.25rem; //the left column that carries date stamps
|
||||
$page-margin-width: 5.25rem; //the left column that carries date stamps: wide
|
||||
//enough for a written-out date in the widest hand
|
||||
$page-padding: 2.25rem;
|
||||
$spine-width: 2.5rem;
|
||||
$book-max-width: 72rem; //leaves the rail room to show its dates
|
||||
|
||||
Reference in new issue
Block a user