forked from trent_larson/crowd-funder-for-time-pwa
Compare commits
15 Commits
design-twe
...
home-infin
| Author | SHA1 | Date | |
|---|---|---|---|
| 540cc21839 | |||
| c182068901 | |||
| aaa1f31945 | |||
| 17c632eb16 | |||
| 41c4cbe61a | |||
| c8402797ad | |||
| 4a09b9b9b1 | |||
| 5db3423301 | |||
| 2b00b243e8 | |||
| f2e5d8168d | |||
| 1d262b8da9 | |||
| 8ed74b71f2 | |||
| 8fb21c3d89 | |||
| 8dbfcd38d3 | |||
| 04df0d4eff |
@@ -6,23 +6,25 @@ tasks:
|
||||
- get it to work on iOS
|
||||
- lock down regenerate_vapid endpoint (so only we admins can do it on demand)
|
||||
- make the app behave correctly when App Notifications are turned off
|
||||
- remove "mute notifications"
|
||||
- remove sleep in py-push-server app.py?
|
||||
- see if we can detect OS-level notifications if turned off
|
||||
- write troubleshooting docs for notifications
|
||||
- make the "App Notifications" toggle on when they turn notifications on
|
||||
- make the "App Notifications" toggle off when they turn notifications off
|
||||
- in py-push-server, when sending a push to a subscriber and we get on a 410 "error #106", delete the subscription record
|
||||
- https://gitea.anomalistdesign.com/trent_larson/py-push-server/pulls/3/files
|
||||
- remove "notification push server" advanced setting since it only makes sense on the current domain
|
||||
- prompt user to install on their home screen
|
||||
|
||||
- .3 fix the Project-location-selection map display to not show on top of bottom icons (and any other UI tweaks on the map flow) assignee-group:ui
|
||||
- back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
|
||||
- fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
|
||||
|
||||
- .3 bug - make or edit a project, choose "Include location", and see the map display shows on top of the bottom icons assignee-group:ui
|
||||
|
||||
- .5 Add infinite scroll to gifts on the home page
|
||||
|
||||
- .5 If notifications are not enabled, add message to front page with link/button to enable
|
||||
|
||||
- fix notification error when first loading the app
|
||||
- 01 server - show all claim details when issued by the issuer
|
||||
- add note after contact addition that they can see your info
|
||||
- enhance help page instructions for debugging
|
||||
- add way to test quickly a push notification
|
||||
@@ -48,8 +50,10 @@ tasks:
|
||||
- Other features - donation vs give, show offers, show give & outstanding totals, show network view, restrict registration, connect to contacts
|
||||
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
||||
|
||||
- remove 'rowid' references (that are sqlite-specific)
|
||||
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
|
||||
- allow some gives even if they aren't registered
|
||||
- 01 make the prod build copy the sw_scripts
|
||||
- 01 send visibility signal as a VC and store it
|
||||
- .5 Add start date to project
|
||||
- .3 check that Android shows "back" buttons on screens without bottom tray
|
||||
- .1 Make give description text box into something that expands as they type?
|
||||
@@ -124,6 +128,8 @@ tasks:
|
||||
- 01 On nearby search, if user starts changing their box but cancels and goes back to the map it is zoomed far out. Fix to fit the box better.
|
||||
- 16 From the home screen, make the quick action even easier.
|
||||
|
||||
- allow some gives even if they aren't registered - maybe someday as a gift to the world, but we really want this to be built via personal connections
|
||||
|
||||
log:
|
||||
- videos for multiple identities https://youtu.be/p8L87AeD76w and for adding time to contacts https://youtu.be/7Yylczevp10 done:2023-03-29
|
||||
- project lists, contact totals & actions, multiple identifiers, stats-world, activity feed, rename of this project file (use "--follow --") milestone:2 done:2023-06-27
|
||||
|
||||
27
src/App.vue
27
src/App.vue
@@ -328,16 +328,23 @@ export default class App extends Vue {
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Got an error initializing notifications:", error);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error Setting Notifications",
|
||||
text: "Got an error setting notifications.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
if (window.location.host.startsWith("localhost")) {
|
||||
console.log(
|
||||
"Ignoring this error getting VAPID for local development:",
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
console.error("Got an error initializing notifications:", error);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error Setting Notifications",
|
||||
text: "Got an error setting notifications.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,24 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- ID notice -->
|
||||
<div
|
||||
v-if="!activeDid"
|
||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||
>
|
||||
<p class="mb-4">
|
||||
<b>Note:</b> Before you can take any action, you need an ID.
|
||||
</p>
|
||||
<router-link
|
||||
:to="{ name: 'start' }"
|
||||
class="inline-block text-md uppercase bg-amber-600 text-white px-4 py-2 rounded-md"
|
||||
>
|
||||
Generate Identity
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<!-- Registration notice -->
|
||||
<!-- We won't show any loading indicator; we'll just pop the message in once we know they need it. -->
|
||||
<!-- We won't show any loading indicator because it usually doesn't change anything. We'll just pop the message in only if we discover that they need it. -->
|
||||
<div
|
||||
v-if="!loadingLimits && !limits?.nextWeekBeginDateTime"
|
||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||
@@ -127,44 +143,13 @@
|
||||
></div>
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
for="toggleMuteNotifications"
|
||||
class="flex items-center justify-between cursor-pointer mt-4"
|
||||
@click="
|
||||
this.$notify(
|
||||
{
|
||||
group: 'modal',
|
||||
type: 'notification-mute',
|
||||
},
|
||||
-1,
|
||||
)
|
||||
"
|
||||
>
|
||||
<!-- label -->
|
||||
<div>Mute Notifications</div>
|
||||
<!-- toggle -->
|
||||
<div class="relative ml-2">
|
||||
<!-- input -->
|
||||
<input
|
||||
type="checkbox"
|
||||
name="toggleMuteNotifications"
|
||||
class="sr-only"
|
||||
disabled
|
||||
/>
|
||||
<!-- line -->
|
||||
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
||||
<!-- dot -->
|
||||
<div
|
||||
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
||||
></div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||
|
||||
<router-link
|
||||
:to="{ name: 'seed-backup' }"
|
||||
v-if="activeDid"
|
||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||
>
|
||||
Backup Identifier Seed
|
||||
@@ -328,7 +313,7 @@
|
||||
:to="{ name: 'identity-switcher' }"
|
||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||
>
|
||||
Switch Identity / No Identity
|
||||
Switch Identity
|
||||
</router-link>
|
||||
|
||||
<button
|
||||
|
||||
@@ -124,7 +124,7 @@ interface Notification {
|
||||
}
|
||||
|
||||
@Component({ components: { QuickNav } })
|
||||
export default class ContactsView extends Vue {
|
||||
export default class ContactAmountssView extends Vue {
|
||||
$notify!: (notification: Notification, timeout?: number) => void;
|
||||
|
||||
activeDid = "";
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
<button
|
||||
class="text-sm bg-blue-600 text-white px-2 py-1.5 rounded-l-md"
|
||||
@click="onClickAddGive(activeDid, contact.did)"
|
||||
title="givenByMeDescriptions[contact.did]"
|
||||
:title="givenByMeDescriptions[contact.did] || ''"
|
||||
>
|
||||
To:
|
||||
{{
|
||||
@@ -190,7 +190,7 @@
|
||||
<button
|
||||
class="text-sm bg-blue-600 text-white px-2 py-1.5 rounded-r-md -ml-1.5 border-l border-blue-400"
|
||||
@click="onClickAddGive(contact.did, activeDid)"
|
||||
title="givenToMeDescriptions[contact.did]"
|
||||
:title="givenToMeDescriptions[contact.did] || ''"
|
||||
>
|
||||
From:
|
||||
{{
|
||||
@@ -367,6 +367,10 @@ export default class ContactsView extends Vue {
|
||||
}
|
||||
|
||||
async loadGives() {
|
||||
if (!this.activeDid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const handleResponse = (
|
||||
resp: { status: number; data: { data: GiveServerRecord[] } },
|
||||
descriptions: Record<string, string>,
|
||||
@@ -401,11 +405,11 @@ export default class ContactsView extends Vue {
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Retrieval Error",
|
||||
text:
|
||||
"Got an error retrieving your " +
|
||||
(useRecipient ? "given" : "received") +
|
||||
" time from the server.",
|
||||
" data from the server.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
@@ -456,12 +460,13 @@ export default class ContactsView extends Vue {
|
||||
this.givenToMeConfirmed = givenToMeConfirmed;
|
||||
this.givenToMeUnconfirmed = givenToMeUnconfirmed;
|
||||
} catch (error) {
|
||||
console.log("Error loading gives", error);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
text: error as string,
|
||||
title: "Load Error",
|
||||
text: "Got an error loading your gives.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
@@ -705,6 +710,7 @@ export default class ContactsView extends Vue {
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error when registering:", error);
|
||||
let userMessage = "There was an error. See logs for more info.";
|
||||
const serverError = error as AxiosError;
|
||||
if (serverError) {
|
||||
@@ -721,7 +727,7 @@ export default class ContactsView extends Vue {
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Registration Error",
|
||||
text: userMessage,
|
||||
},
|
||||
-1,
|
||||
@@ -767,27 +773,28 @@ export default class ContactsView extends Vue {
|
||||
} else {
|
||||
console.error(
|
||||
"Got some bad server response when setting visibility: ",
|
||||
resp.status,
|
||||
resp,
|
||||
);
|
||||
const message =
|
||||
resp.data.error?.message || "Bad server response of " + resp.status;
|
||||
resp.data.error?.message || "Got some error setting visibility.";
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Error Setting Visibility",
|
||||
text: message,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Got some server error when setting visibility:", err);
|
||||
console.error("Got some error when setting visibility:", err);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Error Setting Visibility",
|
||||
text: "Check connectivity and try again.",
|
||||
},
|
||||
-1,
|
||||
@@ -830,19 +837,19 @@ export default class ContactsView extends Vue {
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Error Checking Visibility",
|
||||
text: message,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Caught error from server request to check visibility:", err);
|
||||
console.log("Caught error from request to check visibility:", err);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Error Checking Visibility",
|
||||
text: "Check connectivity and try again.",
|
||||
},
|
||||
-1,
|
||||
@@ -1028,6 +1035,7 @@ export default class ContactsView extends Vue {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error in createAndSubmitGive: ", error);
|
||||
let userMessage = "There was an error. See logs for more info.";
|
||||
const serverError = error as AxiosError;
|
||||
if (serverError) {
|
||||
@@ -1044,7 +1052,7 @@ export default class ContactsView extends Vue {
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Server Error",
|
||||
title: "Error Sending Give",
|
||||
text: userMessage,
|
||||
},
|
||||
-1,
|
||||
|
||||
@@ -28,13 +28,35 @@
|
||||
<p>Somehow call the service-worker self.showNotification</p>
|
||||
|
||||
<h2 class="text-xl font-semibold">Check OS-level permissions</h2>
|
||||
<p>
|
||||
<div>
|
||||
Walk-throughs & screenshots, maybe for all combinations of OS &
|
||||
browsers.
|
||||
</p>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold">Mobile Phone - Apple iOS</h3>
|
||||
<div>
|
||||
Notifications require iOS 16.4 or higher. To check your iOS version,
|
||||
go to Settings > General > About > Software Version.
|
||||
</div>
|
||||
|
||||
<h3 class="text-lg font-semibold">Mobile Phone - Google Android</h3>
|
||||
<div>See the browser section.</div>
|
||||
|
||||
<h3 class="text-lg font-semibold">Desktop - Mac</h3>
|
||||
<div>Requires Mac OS 13.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-semibold">Check browser-level permissions</h2>
|
||||
<p>Walk-throughs & screenshots for browser settings</p>
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold">Mobile Phone - Apple iOS</h3>
|
||||
<div>Make sure your OS (above) supports it.</div>
|
||||
|
||||
<h3 class="text-lg font-semibold">Mobile Phone - Android</h3>
|
||||
<div>Chrome requires version 50.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-semibold">Explain full reset to start again</h2>
|
||||
<p>
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
class="bg-amber-200 rounded-md overflow-hidden text-center px-4 py-3 mb-4"
|
||||
>
|
||||
<p class="text-lg mb-3">
|
||||
You need an <b>identifier</b> before you can record others' giving.
|
||||
You need an <b>identifier</b> before you can record anyone's gives.
|
||||
</p>
|
||||
<router-link
|
||||
:to="{ name: 'start' }"
|
||||
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
|
||||
class="block text-center text-md font-bold uppercase bg-blue-500 text-white mt-2 px-2 py-3 rounded-md"
|
||||
>
|
||||
Create Your Identifier</router-link
|
||||
>
|
||||
@@ -27,17 +27,17 @@
|
||||
v-else-if="!isRegistered"
|
||||
class="bg-amber-200 rounded-md overflow-hidden text-center px-4 py-3 mb-4"
|
||||
>
|
||||
Someone must register your account before you can record others' giving.
|
||||
Someone must register your account before you can record anyone's gives.
|
||||
To do this:
|
||||
<router-link
|
||||
:to="{ name: 'contact-qr' }"
|
||||
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
|
||||
class="block text-center text-md font-bold uppercase bg-blue-500 text-white mt-2 px-2 py-3 rounded-md"
|
||||
>
|
||||
1. Show Them Your Identity Info</router-link
|
||||
>
|
||||
<router-link
|
||||
:to="{ name: 'account' }"
|
||||
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
|
||||
class="block text-center text-md font-bold uppercase bg-blue-500 text-white mt-2 px-2 py-3 rounded-md"
|
||||
>
|
||||
2. Check Your Limits</router-link
|
||||
>
|
||||
@@ -103,42 +103,52 @@
|
||||
showGivenToUser="true"
|
||||
/>
|
||||
|
||||
<!-- Results List -->
|
||||
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
||||
<h2 class="text-xl font-bold mb-4">Latest Activity</h2>
|
||||
<InfiniteScroll @reached-bottom="loadMoreGives">
|
||||
<ul class="border-t border-slate-300">
|
||||
<li
|
||||
class="border-b border-slate-300 py-2"
|
||||
v-for="record in feedData"
|
||||
:key="record.jwtId"
|
||||
>
|
||||
<div
|
||||
class="border-b border-dashed border-slate-400 text-orange-400 pb-2 mb-2 font-bold uppercase text-sm"
|
||||
v-if="record.jwtId == feedLastViewedClaimId"
|
||||
>
|
||||
You've seen all the following
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<fa icon="gift" class="pt-1 pr-2 text-slate-500"></fa>
|
||||
<span class="">{{ this.giveDescription(record) }}</span>
|
||||
<a @click="onClickLoadClaim(record.jwtId)">
|
||||
<fa icon="circle-info" class="pl-2 pt-1 text-slate-500"></fa>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</InfiniteScroll>
|
||||
<div :class="{ hidden: isHiddenSpinner }">
|
||||
<p class="text-slate-500 text-center italic mt-4 mb-4">
|
||||
<fa icon="spinner" class="fa-spin-pulse"></fa> Loading…
|
||||
</p>
|
||||
</div>
|
||||
<ul class="border-t border-slate-300">
|
||||
<li
|
||||
class="border-b border-slate-300 py-2"
|
||||
v-for="record in feedData"
|
||||
:key="record.jwtId"
|
||||
>
|
||||
<div
|
||||
class="border-b border-dashed border-slate-400 text-orange-400 pb-2 mb-2 font-bold uppercase text-sm"
|
||||
v-if="record.jwtId == feedLastViewedId"
|
||||
>
|
||||
You've seen all the following
|
||||
</div>
|
||||
<div class="flex">
|
||||
<fa icon="gift" class="pt-1 pr-2 text-slate-500"></fa>
|
||||
<span class="">{{ this.giveDescription(record) }}</span>
|
||||
<a @click="onClickLoadClaim(record.jwtId)">
|
||||
<fa icon="circle-info" class="pl-2 pt-1 text-slate-500"></fa>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
|
||||
import EntityIcon from "@/components/EntityIcon.vue";
|
||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import { db, accountsDB } from "@/db/index";
|
||||
import { Account } from "@/db/tables/accounts";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
import {
|
||||
@@ -146,11 +156,7 @@ import {
|
||||
GiverInputInfo,
|
||||
GiveServerRecord,
|
||||
} from "@/libs/endorserServer";
|
||||
import { Contact } from "@/db/tables/contacts";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import EntityIcon from "@/components/EntityIcon.vue";
|
||||
import { IIdentifier } from "@veramo/core";
|
||||
import { Account } from "@/db/tables/accounts";
|
||||
|
||||
interface Notification {
|
||||
group: string;
|
||||
@@ -160,7 +166,7 @@ interface Notification {
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: { GiftedDialog, QuickNav, EntityIcon },
|
||||
components: { GiftedDialog, QuickNav, EntityIcon, InfiniteScroll },
|
||||
})
|
||||
export default class HomeView extends Vue {
|
||||
$notify!: (notification: Notification, timeout?: number) => void;
|
||||
@@ -169,10 +175,9 @@ export default class HomeView extends Vue {
|
||||
allContacts: Array<Contact> = [];
|
||||
allMyDids: Array<string> = [];
|
||||
apiServer = "";
|
||||
feedAllLoaded = false;
|
||||
feedData = [];
|
||||
feedPreviousOldestId?: string;
|
||||
feedLastViewedId?: string;
|
||||
feedLastViewedClaimId?: string;
|
||||
isHiddenSpinner = true;
|
||||
isRegistered = false;
|
||||
numAccounts = 0;
|
||||
@@ -212,9 +217,12 @@ export default class HomeView extends Vue {
|
||||
this.apiServer = settings?.apiServer || "";
|
||||
this.activeDid = settings?.activeDid || "";
|
||||
this.allContacts = await db.contacts.toArray();
|
||||
this.feedLastViewedId = settings?.lastViewedClaimId;
|
||||
this.feedLastViewedClaimId = settings?.lastViewedClaimId;
|
||||
this.isRegistered = !!settings?.isRegistered;
|
||||
|
||||
// this returns a Promise but we don't need to wait for it
|
||||
this.updateAllFeed();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
this.$notify(
|
||||
@@ -257,24 +265,33 @@ export default class HomeView extends Vue {
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data loader used by infinite scroller
|
||||
* @param payload is the flag from the InfiniteScroll indicating if it should load
|
||||
**/
|
||||
public async loadMoreGives(payload: boolean) {
|
||||
if (payload) {
|
||||
this.updateAllFeed();
|
||||
}
|
||||
}
|
||||
|
||||
public async updateAllFeed() {
|
||||
this.isHiddenSpinner = false;
|
||||
await this.retrieveClaims(this.apiServer, this.feedPreviousOldestId)
|
||||
await this.retrieveGives(this.apiServer, this.feedPreviousOldestId)
|
||||
.then(async (results) => {
|
||||
if (results.data.length > 0) {
|
||||
this.feedData = this.feedData.concat(results.data);
|
||||
this.feedAllLoaded = results.hitLimit;
|
||||
this.feedPreviousOldestId =
|
||||
results.data[results.data.length - 1].jwtId;
|
||||
// The following update is only done on the first load.
|
||||
if (
|
||||
this.feedLastViewedId == null ||
|
||||
this.feedLastViewedId < results.data[0].jwtId
|
||||
this.feedLastViewedClaimId == null ||
|
||||
this.feedLastViewedClaimId < results.data[0].jwtId
|
||||
) {
|
||||
await db.open();
|
||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||
lastViewedClaimId: results.data[0].jwtId,
|
||||
});
|
||||
// but not for this page because we need to remember what it was before
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -284,17 +301,22 @@ export default class HomeView extends Vue {
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Export Error",
|
||||
title: "Feed Error",
|
||||
text: e.userMessage || "There was an error retrieving feed data.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
});
|
||||
|
||||
this.isHiddenSpinner = true;
|
||||
}
|
||||
|
||||
public async retrieveClaims(endorserApiServer: string, beforeId?: string) {
|
||||
/**
|
||||
* Retrieve claims in reverse chronological order
|
||||
*
|
||||
* @param beforeId the earliest ID (of previous searches) to search earlier
|
||||
* @return claims in reverse chronological order
|
||||
*/
|
||||
public async retrieveGives(endorserApiServer: string, beforeId?: string) {
|
||||
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
|
||||
const response = await fetch(
|
||||
endorserApiServer + "/api/v2/report/gives?" + beforeQuery,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
maxlength="5000"
|
||||
></textarea>
|
||||
<div class="text-xs text-slate-500 italic -mt-3 mb-4">
|
||||
{{ fullClaim.description.length }}/5000 max. characters
|
||||
{{ fullClaim.description?.length }}/5000 max. characters
|
||||
</div>
|
||||
|
||||
<input
|
||||
|
||||
@@ -88,7 +88,7 @@ export default class NewIdentifierView extends Vue {
|
||||
|
||||
this.loading = false;
|
||||
setTimeout(() => {
|
||||
this.$router.push({ name: "account" });
|
||||
this.$router.push({ name: "home" });
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<div v-if="activeDid" class="text-center">
|
||||
<div v-if="activeDid" class="mb-4">
|
||||
<div class="text-center">
|
||||
<button
|
||||
@click="openOfferDialog({ name: 'you', did: activeDid })"
|
||||
class="block w-full text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md"
|
||||
@@ -99,17 +99,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div v-if="activeDid" class="text-center">
|
||||
<div v-if="activeDid">
|
||||
<div class="text-center">
|
||||
<button
|
||||
@click="openGiftDialog({ name: 'you', did: activeDid })"
|
||||
class="block w-full text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md"
|
||||
>
|
||||
I gave…
|
||||
</button>
|
||||
<p class="mt-2 mb-4 text-center">Or, record a gift from:</p>
|
||||
<p class="mt-2 mb-4 text-center">Or, record a contribution from:</p>
|
||||
</div>
|
||||
<p v-if="!activeDid" class="mt-2 mb-4">Record a gift from:</p>
|
||||
|
||||
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
|
||||
<li @click="openGiftDialog()">
|
||||
@@ -234,28 +233,32 @@
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">
|
||||
Contributions To This Idea
|
||||
</h3>
|
||||
<ul>
|
||||
<li v-for="plan in fulfillersToThis" :key="plan.handleId">
|
||||
<!-- centering because long, wrapped project names didn't left align with blank or "text-left" -->
|
||||
<div class="text-center">
|
||||
<div v-for="plan in fulfillersToThis" :key="plan.handleId">
|
||||
<button
|
||||
@click="onClickLoadProject(plan.handleId)"
|
||||
class="text-blue-500"
|
||||
>
|
||||
{{ plan.name }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="fulfilledByThis" class="bg-slate-100 px-4 py-3 rounded-md">
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">
|
||||
Contributions By This Idea
|
||||
</h3>
|
||||
<button
|
||||
@click="onClickLoadProject(fulfilledByThis.handleId)"
|
||||
class="text-blue-500"
|
||||
>
|
||||
{{ fulfilledByThis.name }}
|
||||
</button>
|
||||
<!-- centering because long, wrapped project names didn't left align with blank or "text-left" -->
|
||||
<div class="text-center">
|
||||
<button
|
||||
@click="onClickLoadProject(fulfilledByThis.handleId)"
|
||||
class="text-blue-500"
|
||||
>
|
||||
{{ fulfilledByThis.name }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -356,12 +359,6 @@ export default class ProjectViewView extends Vue {
|
||||
.equals(activeDid)
|
||||
.first()) as Account;
|
||||
const identity = JSON.parse(account?.identity || "null");
|
||||
|
||||
if (!identity) {
|
||||
throw new Error(
|
||||
"Attempted to load project records with no identity available.",
|
||||
);
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
|
||||
|
||||
19
web-push.md
19
web-push.md
@@ -400,3 +400,22 @@ While notifications are turned on, the user can tap on the App Notifications tog
|
||||
* Active. (User can change to Muted when the user mutes notifications.)
|
||||
* Muted. (User can change to Active when the user toggles it.)
|
||||
(Turning mute off automatically after some amount of time is not planned in version 1.)
|
||||
|
||||
|
||||
# TROUBLESHOOTING
|
||||
|
||||
## Desktop
|
||||
|
||||
#### Firefox
|
||||
|
||||
Go to `about:debugging` and click on `Inspect` for the service worker.
|
||||
|
||||
#### Chrome
|
||||
|
||||
Go to `chrome://inspect/#service-workers` and click on `Inspect` for the service worker.
|
||||
|
||||
## Mobile
|
||||
|
||||
#### Android
|
||||
|
||||
#### iOS
|
||||
|
||||
Reference in New Issue
Block a user