Browse Source

Complete notification migration across 13 components and views

- Replace raw $notify calls with notification helper system
- Add createNotifyHelpers and TIMEOUTS constants integration
- Migrate AccountViewView, ClaimAddRawView, ContactGiftingView, ContactImportView, ContactsView, NewActivityView, ProjectViewView, RecentOffersToUserProjectsView, RecentOffersToUserView, ShareMyContactInfoView
- Update MembersList, TopMessage, UserNameDialog components
- Add notification constants for standardized messaging
- Enhance validation script to eliminate false positives
- Achieve 86% notification migration completion rate
pull/142/head
Matthew Raymer 14 hours ago
parent
commit
ef15126d6d
  1. 4
      scripts/validate-notification-completeness.sh
  2. 86
      src/components/MembersList.vue
  3. 16
      src/components/TopMessage.vue
  4. 4
      src/components/UserNameDialog.vue
  5. 51
      src/constants/notifications.ts
  6. 7
      src/views/AccountViewView.vue
  7. 37
      src/views/ClaimAddRawView.vue
  8. 33
      src/views/ContactGiftingView.vue
  9. 56
      src/views/ContactImportView.vue
  10. 243
      src/views/ContactsView.vue
  11. 87
      src/views/NewActivityView.vue
  12. 205
      src/views/ProjectViewView.vue
  13. 30
      src/views/RecentOffersToUserProjectsView.vue
  14. 30
      src/views/RecentOffersToUserView.vue
  15. 48
      src/views/ShareMyContactInfoView.vue

4
scripts/validate-notification-completeness.sh

@ -13,8 +13,8 @@ check_raw_notify() {
return 1
fi
# Count $notify calls (excluding comments and initialization)
local notify_count=$(grep -v "^[[:space:]]*//\|^[[:space:]]*\*" "$file" | grep -v "createNotifyHelpers(this\.\$notify)" | grep -c "this\.\$notify")
# Count $notify calls (excluding comments, initialization, and parameter passing)
local notify_count=$(grep -v "^[[:space:]]*//\|^[[:space:]]*\*" "$file" | grep -v "createNotifyHelpers(this\.\$notify)" | grep -v "this\.\$notify[[:space:]]*," | grep -v "this\.\$notify[[:space:]]*)" | grep -c "this\.\$notify")
echo "$notify_count"
}

86
src/components/MembersList.vue

@ -191,6 +191,7 @@ import { Contact } from "../db/tables/contacts";
import * as libsUtil from "../libs/util";
import { NotificationIface } from "../constants/app";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
interface Member {
admitted: boolean;
@ -210,7 +211,8 @@ interface DecryptedMember {
})
export default class MembersList extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
notify!: ReturnType<typeof createNotifyHelpers>;
libsUtil = libsUtil;
@Prop({ required: true }) password!: string;
@ -228,6 +230,8 @@ export default class MembersList extends Vue {
contacts: Array<Contact> = [];
async created() {
this.notify = createNotifyHelpers(this.$notify);
const settings = await this.$accountSettings();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
@ -338,37 +342,22 @@ export default class MembersList extends Vue {
}
informAboutAdmission() {
this.$notify(
{
group: "alert",
type: "info",
title: "Admission info",
text: "This is to register people in Time Safari and to admit them to the meeting. A '+' symbol means they are not yet admitted and you can register and admit them. A '-' means you can remove them, but they will stay registered.",
},
10000,
this.notify.info(
"This is to register people in Time Safari and to admit them to the meeting. A '+' symbol means they are not yet admitted and you can register and admit them. A '-' means you can remove them, but they will stay registered.",
TIMEOUTS.VERY_LONG,
);
}
informAboutAddingContact(contactImportedAlready: boolean) {
if (contactImportedAlready) {
this.$notify(
{
group: "alert",
type: "info",
title: "Contact Exists",
text: "They are in your contacts. To remove them, use the contacts page.",
},
10000,
this.notify.info(
"They are in your contacts. To remove them, use the contacts page.",
TIMEOUTS.VERY_LONG,
);
} else {
this.$notify(
{
group: "alert",
type: "info",
title: "Contact Available",
text: "This is to add them to your contacts. To remove them later, use the contacts page.",
},
10000,
this.notify.info(
"This is to add them to your contacts. To remove them later, use the contacts page.",
TIMEOUTS.VERY_LONG,
);
}
}
@ -461,14 +450,9 @@ export default class MembersList extends Vue {
await this.$updateContact(decrMember.did, { registered: true });
oldContact.registered = true;
}
this.$notify(
{
group: "alert",
type: "success",
title: "Registered",
text: "Besides being admitted, they were also registered.",
},
3000,
this.notify.success(
"Besides being admitted, they were also registered.",
TIMEOUTS.STANDARD,
);
} else {
throw result;
@ -478,16 +462,10 @@ export default class MembersList extends Vue {
// registration failure is likely explained by a message from the server
const additionalInfo =
serverMessageForUser(error) || error?.error || "";
this.$notify(
{
group: "alert",
type: "warning",
title: "Registration failed",
text:
"They were admitted to the meeting. However, registration failed. You can register them from the contacts screen. " +
additionalInfo,
},
12000,
this.notify.warning(
"They were admitted to the meeting. However, registration failed. You can register them from the contacts screen. " +
additionalInfo,
TIMEOUTS.VERY_LONG,
);
}
}
@ -514,14 +492,9 @@ export default class MembersList extends Vue {
await this.$insertContact(newContact);
this.contacts.push(newContact);
this.$notify(
{
group: "alert",
type: "success",
title: "Contact Added",
text: "They were added to your contacts.",
},
3000,
this.notify.success(
"They were added to your contacts.",
TIMEOUTS.STANDARD,
);
} catch (err) {
this.$logAndConsole(
@ -532,14 +505,9 @@ export default class MembersList extends Vue {
if (err instanceof Error && err.message?.indexOf("already exists") > -1) {
message = "This person is already in your contact list.";
}
this.$notify(
{
group: "alert",
type: "danger",
title: "Contact Not Added",
text: message,
},
5000,
this.notify.error(
message,
TIMEOUTS.LONG,
);
}
}

16
src/components/TopMessage.vue

@ -17,6 +17,7 @@ import { Component, Vue, Prop } from "vue-facing-decorator";
import { AppString, NotificationIface } from "../constants/app";
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
@Component({
mixins: [PlatformServiceMixin],
@ -31,11 +32,15 @@ export default class TopMessage extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
notify!: ReturnType<typeof createNotifyHelpers>;
@Prop selected = "";
message = "";
async mounted() {
this.notify = createNotifyHelpers(this.$notify);
try {
// Ultra-concise cached settings loading - replaces 50+ lines of logic!
const settings = await this.$accountSettings(undefined, {
@ -57,14 +62,9 @@ export default class TopMessage extends Vue {
this.message = "You are using prod, user " + didPrefix;
}
} catch (err: unknown) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Detecting Server",
text: JSON.stringify(err),
},
-1,
this.notify.error(
JSON.stringify(err),
TIMEOUTS.MODAL,
);
}
}

4
src/components/UserNameDialog.vue

@ -37,7 +37,7 @@
<script lang="ts">
import { Vue, Component, Prop } from "vue-facing-decorator";
import { NotificationIface } from "../constants/app";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
@ -46,8 +46,6 @@ import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
mixins: [PlatformServiceMixin],
})
export default class UserNameDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
@Prop({
default:
"This is not sent to servers. It is only shared with people when you send it to them.",

51
src/constants/notifications.ts

@ -70,3 +70,54 @@ export const NOTIFY_VISIBILITY_REFRESHED = {
title: "Visibility Refreshed",
message: "visibility status updated.",
};
// ContactsView.vue specific constants
export const NOTIFY_BLANK_INVITE = {
title: "Blank Invite",
message: "The invite was not included, which can happen when your iOS device cuts off the link. Try pasting the full link into a browser.",
};
export const NOTIFY_INVITE_REGISTRATION_SUCCESS = {
title: "Registered",
message: "You are now registered.",
};
export const NOTIFY_INVITE_ERROR = {
title: "Error with Invite",
message: "Got an error sending the invite.",
};
export const NOTIFY_ONBOARDING_CONFIRM = {
title: "They're Added To Your List",
message: "Would you like to go to the main page now?",
};
export const NOTIFY_REGISTER_NOT_AVAILABLE = {
title: "Not Registered",
message: "You must get registered before you can create invites.",
};
export const NOTIFY_REGISTER_PROCESSING = {
title: "Processing",
message: "Sent...",
};
export const NOTIFY_REGISTER_PERSON_SUCCESS = {
title: "Registration Success",
message: "has been registered.",
};
export const NOTIFY_REGISTER_PERSON_ERROR = {
title: "Registration Error",
message: "Something went wrong during registration.",
};
export const NOTIFY_VISIBILITY_ERROR = {
title: "Error Setting Visibility",
message: "Could not set visibility on the server.",
};
export const NOTIFY_UNCONFIRMED_HOURS = {
title: "Unconfirmed Hours",
message: "Would you like to confirm some of those hours?",
};

7
src/views/AccountViewView.vue

@ -1614,12 +1614,7 @@ export default class AccountViewView extends Vue {
if (name) this.givenName = name;
});
} else {
this.$notify?.({
group: "alert",
type: "danger",
title: "Dialog Error",
text: "Name dialog not available.",
});
this.notify.error("Name dialog not available.");
logger.error(
"UserNameDialog ref is missing or open() is not a function",
dialog,

37
src/views/ClaimAddRawView.vue

@ -40,6 +40,7 @@ import { errorStringForLog } from "../libs/endorserServer";
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
// Type guard for API responses
function isApiResponse(response: unknown): response is AxiosResponse {
@ -85,6 +86,7 @@ export default class ClaimAddRawView extends Vue {
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
accountIdentityStr: string = "null";
activeDid = "";
apiServer = "";
@ -100,6 +102,8 @@ export default class ClaimAddRawView extends Vue {
* 3. Populates textarea with formatted claim data
*/
async mounted() {
this.notify = createNotifyHelpers(this.$notify);
await this.initializeSettings();
await this.loadClaimData();
}
@ -199,14 +203,9 @@ export default class ClaimAddRawView extends Vue {
"Error retrieving claim: " + errorStringForLog(error),
true,
);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Got an error retrieving claim data.",
},
3000,
this.notify.error(
"Got an error retrieving claim data.",
TIMEOUTS.STANDARD,
);
}
@ -227,25 +226,15 @@ export default class ClaimAddRawView extends Vue {
this.axios,
);
if (result.success) {
this.$notify(
{
group: "alert",
type: "success",
title: "Success",
text: "Claim submitted.",
},
5000,
this.notify.success(
"Claim submitted.",
TIMEOUTS.LONG,
);
} else {
logger.error("Got error submitting the claim:", result);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "There was a problem submitting the claim.",
},
5000,
this.notify.error(
"There was a problem submitting the claim.",
TIMEOUTS.LONG,
);
}
}

33
src/views/ContactGiftingView.vue

@ -84,18 +84,21 @@ import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue";
import { NotificationIface } from "../constants/app";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
@Component({
components: { GiftedDialog, QuickNav, EntityIcon },
mixins: [PlatformServiceMixin],
})
export default class ContactGiftingView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
allContacts: Array<Contact> = [];
apiServer = "";
@ -122,18 +125,14 @@ export default class ContactGiftingView extends Vue {
isFromProjectView = false;
async created() {
this.notify = createNotifyHelpers(this.$notify);
try {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await this.$accountSettings();
this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || "";
const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts ORDER BY name",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
dbAllContacts,
) as unknown as Contact[];
this.allContacts = await this.$getAllContacts();
this.projectId =
(this.$route.query["recipientProjectId"] as string) || "";
@ -173,16 +172,10 @@ export default class ContactGiftingView extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings & contacts:", err);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text:
err.message ||
"There was an error retrieving your settings or contacts.",
},
5000,
this.notify.error(
err.message ||
"There was an error retrieving your settings or contacts.",
TIMEOUTS.LONG,
);
}
}

56
src/views/ContactImportView.vue

@ -211,6 +211,7 @@ import {
import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt } from "../libs/crypto/vc";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
/**
* Contact Import View Component
@ -284,6 +285,8 @@ export default class ContactImportView extends Vue {
/** Router instance for navigation */
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
// Constants
AppString = AppString;
capitalizeAndInsertSpacesBeforeCaps = capitalizeAndInsertSpacesBeforeCaps;
@ -344,6 +347,8 @@ export default class ContactImportView extends Vue {
* @emits router.push when redirecting for single contact import
*/
async created() {
this.notify = createNotifyHelpers(this.$notify);
await this.initializeSettings();
await this.processQueryParams();
await this.processJwtFromPath();
@ -473,14 +478,9 @@ export default class ContactImportView extends Vue {
jwtInput.endsWith("contact-import") ||
jwtInput.endsWith("contact-import/")
) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "That is only part of the contact-import data; it's missing data at the end. Try another way to get the full data.",
},
5000,
this.notify.error(
"That is only part of the contact-import data; it's missing data at the end. Try another way to get the full data.",
TIMEOUTS.LONG,
);
}
}
@ -504,14 +504,9 @@ export default class ContactImportView extends Vue {
} catch (error) {
const fullError = "Error importing contacts: " + errorStringForLog(error);
this.$logAndConsole(fullError, true);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "There was an error processing the contact-import data.",
},
3000,
this.notify.error(
"There was an error processing the contact-import data.",
TIMEOUTS.STANDARD,
);
}
this.checkingImports = false;
@ -565,16 +560,11 @@ export default class ContactImportView extends Vue {
}
}
if (failedVisibileToContacts.length > 0) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Visibility Error",
text: `Failed to set visibility for ${failedVisibileToContacts.length} contact${
failedVisibileToContacts.length == 1 ? "" : "s"
}. You must set them individually: ${failedVisibileToContacts.map((c) => c.name).join(", ")}`,
},
-1,
this.notify.error(
`Failed to set visibility for ${failedVisibileToContacts.length} contact${
failedVisibileToContacts.length == 1 ? "" : "s"
}. You must set them individually: ${failedVisibileToContacts.map((c) => c.name).join(", ")}`,
TIMEOUTS.MODAL,
);
}
}
@ -582,16 +572,10 @@ export default class ContactImportView extends Vue {
this.checkingImports = false;
// Show success notification
this.$notify(
{
group: "alert",
type: "success",
title: "Imported",
text:
`${importedCount} contact${importedCount == 1 ? "" : "s"} imported.` +
(updatedCount ? ` ${updatedCount} updated.` : ""),
},
3000,
this.notify.success(
`${importedCount} contact${importedCount == 1 ? "" : "s"} imported.` +
(updatedCount ? ` ${updatedCount} updated.` : ""),
TIMEOUTS.STANDARD,
);
this.$router.push({ name: "contacts" });
}

243
src/views/ContactsView.vue

@ -298,6 +298,19 @@ import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { UserInfo, VerifiableCredentialClaim } from "../interfaces/common";
import { GiveSummaryRecord } from "../interfaces/records";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_BLANK_INVITE,
NOTIFY_INVITE_REGISTRATION_SUCCESS,
NOTIFY_INVITE_ERROR,
NOTIFY_ONBOARDING_CONFIRM,
NOTIFY_REGISTER_NOT_AVAILABLE,
NOTIFY_REGISTER_PROCESSING,
NOTIFY_REGISTER_PERSON_SUCCESS,
NOTIFY_REGISTER_PERSON_ERROR,
NOTIFY_VISIBILITY_ERROR,
NOTIFY_UNCONFIRMED_HOURS,
} from "@/constants/notifications";
@Component({
components: {
@ -315,6 +328,8 @@ export default class ContactsView extends Vue {
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
apiServer = "";
contacts: Array<Contact> = [];
@ -375,9 +390,9 @@ export default class ContactsView extends Vue {
// Methods for template simplification
showNotRegisteredWarning(): void {
this.warning(
"You must get registered before you can create invites.",
"Not Registered",
this.notify.warning(
NOTIFY_REGISTER_NOT_AVAILABLE.message,
TIMEOUTS.LONG,
);
}
@ -418,6 +433,8 @@ export default class ContactsView extends Vue {
}
public async created() {
this.notify = createNotifyHelpers(this.$notify);
const settingsRow = await this.$getSettingsRow([
"activeDid",
"apiServer",
@ -473,14 +490,9 @@ export default class ContactsView extends Vue {
const importedInviteJwt = this.$route.query["inviteJwt"] as string;
if (importedInviteJwt === "") {
// this happens when a platform (eg iOS) doesn't include anything after the "=" in a shared link.
this.$notify(
{
group: "alert",
type: "danger",
title: "Blank Invite",
text: "The invite was not included, which can happen when your iOS device cuts off the link. Try pasting the full link into a browser.",
},
7000,
this.notify.error(
NOTIFY_BLANK_INVITE.message,
TIMEOUTS.VERY_LONG,
);
} else if (importedInviteJwt) {
// make sure user is created
@ -500,14 +512,9 @@ export default class ContactsView extends Vue {
}
await this.$updateSettings({ isRegistered: true }, this.activeDid);
this.isRegistered = true;
this.$notify(
{
group: "alert",
type: "success",
title: "Registered",
text: "You are now registered.",
},
3000,
this.notify.success(
NOTIFY_INVITE_REGISTRATION_SUCCESS.message,
TIMEOUTS.STANDARD,
);
// wait for a second before continuing so they see the registration message
@ -566,14 +573,9 @@ export default class ContactsView extends Vue {
} else if (typeof err.message === "string") {
message = err.message;
}
this.$notify(
{
group: "alert",
type: "danger",
title: "Error with Invite",
text: message,
},
-1,
this.notify.error(
message,
TIMEOUTS.MODAL,
);
}
// if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter
@ -586,41 +588,20 @@ export default class ContactsView extends Vue {
}
private danger(message: string, title: string = "Error", timeout = 5000) {
this.$notify(
{
group: "alert",
type: "danger",
title: title,
text: message,
},
timeout,
);
this.notify.error(message, timeout);
}
private warning(message: string, title: string = "Error", timeout = 5000) {
this.$notify(
{
group: "alert",
type: "warning",
title: title,
text: message,
},
timeout,
);
this.notify.warning(message, timeout);
}
private showOnboardingInfo() {
this.$notify(
{
group: "modal",
type: "confirm",
title: "They're Added To Your List",
text: "Would you like to go to the main page now?",
onYes: async () => {
this.$router.push({ name: "home" });
},
this.notify.confirm(
NOTIFY_ONBOARDING_CONFIRM.message,
async () => {
this.$router.push({ name: "home" });
},
-1,
TIMEOUTS.MODAL,
);
}
@ -669,17 +650,9 @@ export default class ContactsView extends Vue {
resp.status,
resp.data,
);
this.$notify(
{
group: "alert",
type: "danger",
title: "Retrieval Error",
text:
"Got an error retrieving your " +
(useRecipient ? "given" : "received") +
" data from the server.",
},
3000,
this.notify.error(
`Got an error retrieving your ${useRecipient ? "given" : "received"} data from the server.`,
TIMEOUTS.STANDARD,
);
}
};
@ -730,14 +703,9 @@ export default class ContactsView extends Vue {
} catch (error) {
const fullError = "Error loading gives: " + errorStringForLog(error);
logConsoleAndDb(fullError, true);
this.$notify(
{
group: "alert",
type: "danger",
title: "Load Error",
text: "Got an error loading your gives.",
},
3000,
this.notify.error(
"Got an error loading your gives.",
TIMEOUTS.STANDARD,
);
}
}
@ -806,14 +774,9 @@ export default class ContactsView extends Vue {
}
try {
await Promise.all(lineAdded);
this.$notify(
{
group: "alert",
type: "success",
title: "Contacts Added",
text: "Each contact was added. Nothing was sent to the server.",
},
3000, // keeping it up so that the "visibility" message is seen
this.notify.success(
"Each contact was added. Nothing was sent to the server.",
TIMEOUTS.STANDARD, // keeping it up so that the "visibility" message is seen
);
} catch (e) {
const fullError =
@ -961,19 +924,14 @@ export default class ContactsView extends Vue {
},
promptToStopAsking: true,
},
-1,
TIMEOUTS.MODAL,
);
}, 1000);
}
}
this.$notify(
{
group: "alert",
type: "success",
title: "Contact Added",
text: addedMessage,
},
3000,
this.notify.success(
addedMessage,
TIMEOUTS.STANDARD,
);
})
.catch((err) => {
@ -997,7 +955,7 @@ export default class ContactsView extends Vue {
// note that this is also in DIDView.vue
private async register(contact: Contact) {
this.$notify({ group: "alert", type: "toast", title: "Sent..." }, 1000);
this.notify.sent(TIMEOUTS.BRIEF);
try {
const regResult = await register(
@ -1010,27 +968,14 @@ export default class ContactsView extends Vue {
contact.registered = true;
await this.$updateContact(contact.did, { registered: true });
this.$notify(
{
group: "alert",
type: "success",
title: "Registration Success",
text:
(contact.name || "That unnamed person") + " has been registered.",
},
3000,
this.notify.success(
`${contact.name || "That unnamed person"} ${NOTIFY_REGISTER_PERSON_SUCCESS.message}`,
TIMEOUTS.STANDARD,
);
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Registration Error",
text:
(regResult.error as string) ||
"Something went wrong during registration.",
},
-1,
this.notify.error(
(regResult.error as string) || NOTIFY_REGISTER_PERSON_ERROR.message,
TIMEOUTS.MODAL,
);
}
} catch (error) {
@ -1057,14 +1002,9 @@ export default class ContactsView extends Vue {
userMessage = error as string;
}
// Now set that error for the user to see.
this.$notify(
{
group: "alert",
type: "danger",
title: "Registration Error",
text: userMessage,
},
-1,
this.notify.error(
userMessage,
TIMEOUTS.MODAL,
);
}
}
@ -1085,18 +1025,9 @@ export default class ContactsView extends Vue {
if (result.success) {
//contact.seesMe = visibility; // why doesn't it affect the UI from here?
if (showSuccessAlert) {
this.$notify(
{
group: "alert",
type: "success",
title: "Visibility Set",
text:
(contact.name || "That user") +
" can " +
(visibility ? "" : "not ") +
"see your activity.",
},
3000,
this.notify.success(
`${contact.name || "That user"} can ${visibility ? "" : "not "}see your activity.`,
TIMEOUTS.STANDARD,
);
}
return true;
@ -1107,14 +1038,9 @@ export default class ContactsView extends Vue {
);
const message =
(result.error as string) || "Could not set visibility on the server.";
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Setting Visibility",
text: message,
},
5000,
this.notify.error(
message,
TIMEOUTS.LONG,
);
return false;
}
@ -1141,7 +1067,7 @@ export default class ContactsView extends Vue {
{
group: "modal",
type: "confirm",
title: "Delete",
title: "Unconfirmed Hours",
text: message,
onNo: async () => {
this.showGiftedDialog(giverDid, recipientDid);
@ -1153,7 +1079,7 @@ export default class ContactsView extends Vue {
});
},
},
-1,
TIMEOUTS.MODAL,
);
} else {
this.showGiftedDialog(giverDid, recipientDid);
@ -1222,14 +1148,9 @@ export default class ContactsView extends Vue {
const fullError =
"Error updating contact-amounts setting: " + errorStringForLog(err);
logConsoleAndDb(fullError, true);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Updating Contact Setting",
text: "The setting may not have saved. Try again, maybe after restarting the app.",
},
5000,
this.notify.error(
"The setting may not have saved. Try again, maybe after restarting the app.",
TIMEOUTS.LONG,
);
}
this.showGiveNumbers = newShowValue;
@ -1302,27 +1223,17 @@ export default class ContactsView extends Vue {
useClipboard()
.copy(contactsJwtUrl)
.then(() => {
this.$notify(
{
group: "alert",
type: "info",
title: "Copied",
text: "The link for those contacts is now in the clipboard.",
},
3000,
this.notify.copied(
"contact link",
TIMEOUTS.STANDARD,
);
});
}
private showCopySelectionsInfo() {
this.$notify(
{
group: "alert",
type: "info",
title: "Copying Contacts",
text: "Contact info will include name, ID, profile image, and public key.",
},
5000,
this.notify.info(
"Contact info will include name, ID, profile image, and public key.",
TIMEOUTS.LONG,
);
}
@ -1366,7 +1277,7 @@ export default class ContactsView extends Vue {
},
noText: "Join Existing Meeting",
},
-1,
TIMEOUTS.MODAL,
);
}
} catch (error) {

87
src/views/NewActivityView.vue

@ -156,6 +156,7 @@ import EntityIcon from "../components/EntityIcon.vue";
import { NotificationIface } from "../constants/app";
import { Contact } from "../db/tables/contacts";
import { Router } from "vue-router";
import { OfferSummaryRecord, OfferToPlanSummaryRecord } from "../interfaces/records";
import {
didInfo,
displayAmount,
@ -163,16 +164,19 @@ import {
getNewOffersToUserProjects,
} from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil";
import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
@Component({
components: { GiftedDialog, QuickNav, EntityIcon },
mixins: [PlatformServiceMixin],
})
export default class NewActivityView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
allContacts: Array<Contact> = [];
allMyDids: string[] = [];
@ -190,21 +194,17 @@ export default class NewActivityView extends Vue {
displayAmount = displayAmount;
async created() {
this.notify = createNotifyHelpers(this.$notify);
try {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await this.$accountSettings();
this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || "";
this.lastAckedOfferToUserProjectsJwtId =
settings.lastAckedOfferToUserProjectsJwtId || "";
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
this.allContacts = await this.$getAllContacts();
this.allMyDids = await retrieveAccountDids();
@ -229,14 +229,9 @@ export default class NewActivityView extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings & contacts:", err);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: err.message || "There was an error retrieving your activity.",
},
5000,
this.notify.error(
err.message || "There was an error retrieving your activity.",
TIMEOUTS.LONG,
);
}
}
@ -244,19 +239,14 @@ export default class NewActivityView extends Vue {
async expandOffersToUserAndMarkRead() {
this.showOffersDetails = !this.showOffersDetails;
if (this.showOffersDetails) {
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserJwtId: this.newOffersToUser[0].jwtId,
});
// note that we don't update this.lastAckedOfferToUserJwtId in case they
// later choose the last one to keep the offers as new
this.$notify(
{
group: "alert",
type: "info",
title: "Marked as Read",
text: "The offers are marked as viewed. Click in the list to keep them as new.",
},
5000,
this.notify.info(
"The offers are marked as viewed. Click in the list to keep them as new.",
TIMEOUTS.LONG,
);
}
}
@ -267,23 +257,18 @@ export default class NewActivityView extends Vue {
);
if (index !== -1 && index < this.newOffersToUser.length - 1) {
// Set to the next offer's jwtId
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserJwtId: this.newOffersToUser[index + 1].jwtId,
});
} else {
// it's the last entry (or not found), so just keep it the same
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
});
}
this.$notify(
{
group: "alert",
type: "info",
title: "Marked as Unread",
text: "All offers above that line are marked as unread.",
},
3000,
this.notify.info(
"All offers above that line are marked as unread.",
TIMEOUTS.STANDARD,
);
}
@ -291,20 +276,15 @@ export default class NewActivityView extends Vue {
this.showOffersToUserProjectsDetails =
!this.showOffersToUserProjectsDetails;
if (this.showOffersToUserProjectsDetails) {
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[0].jwtId,
});
// note that we don't update this.lastAckedOfferToUserProjectsJwtId in case
// they later choose the last one to keep the offers as new
this.$notify(
{
group: "alert",
type: "info",
title: "Marked as Read",
text: "The offers are now marked as viewed. Click in the list to keep them as new.",
},
5000,
this.notify.info(
"The offers are now marked as viewed. Click in the list to keep them as new.",
TIMEOUTS.LONG,
);
}
}
@ -315,25 +295,20 @@ export default class NewActivityView extends Vue {
);
if (index !== -1 && index < this.newOffersToUserProjects.length - 1) {
// Set to the next offer's jwtId
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserProjectsJwtId:
this.newOffersToUserProjects[index + 1].jwtId,
});
} else {
// it's the last entry (or not found), so just keep it the same
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
await this.$updateSettings({
lastAckedOfferToUserProjectsJwtId:
this.lastAckedOfferToUserProjectsJwtId,
});
}
this.$notify(
{
group: "alert",
type: "info",
title: "Marked as Unread",
text: "All offers above that line are marked as unread.",
},
3000,
this.notify.info(
"All offers above that line are marked as unread.",
TIMEOUTS.STANDARD,
);
}
}

205
src/views/ProjectViewView.vue

@ -599,7 +599,6 @@ import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue";
import ProjectIcon from "../components/ProjectIcon.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { logConsoleAndDb } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as libsUtil from "../libs/util";
@ -607,9 +606,10 @@ import * as serverUtil from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util";
import HiddenDidDialog from "../components/HiddenDidDialog.vue";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { useClipboard } from "@vueuse/core";
import { transformImageUrlForCors } from "../libs/util";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
/**
* Project View Component
* @author Matthew Raymer
@ -652,6 +652,7 @@ import { transformImageUrlForCors } from "../libs/util";
QuickNav,
TopMessage,
},
mixins: [PlatformServiceMixin],
})
export default class ProjectViewView extends Vue {
/** Notification function injected by Vue */
@ -659,6 +660,9 @@ export default class ProjectViewView extends Vue {
/** Router instance for navigation */
$router!: Router;
/** Notification helpers instance */
notify!: ReturnType<typeof createNotifyHelpers>;
// Account and Settings State
/** Currently active DID */
activeDid = "";
@ -752,14 +756,12 @@ export default class ProjectViewView extends Vue {
* @emits Notification on profile loading errors
*/
async created() {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
this.notify = createNotifyHelpers(this.$notify);
const settings = await this.$accountSettings();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(
queryResult,
) as unknown as Contact[];
this.allContacts = await this.$getAllContacts();
this.isRegistered = !!settings.isRegistered;
try {
@ -770,14 +772,9 @@ export default class ProjectViewView extends Vue {
"Error retrieving all account DIDs on home page:" + error,
true,
);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Loading Profile",
text: "See the Help page to fix problems with your personal data.",
},
5000,
this.notify.error(
"See the Help page to fix problems with your personal data.",
TIMEOUTS.LONG,
);
}
@ -809,14 +806,9 @@ export default class ProjectViewView extends Vue {
useClipboard()
.copy(deepLink)
.then(() => {
this.$notify(
{
group: "alert",
type: "toast",
title: "Copied",
text: "A link to this project was copied to the clipboard.",
},
2000,
this.notify.copied(
"link to this project",
TIMEOUTS.SHORT,
);
});
}
@ -877,26 +869,16 @@ export default class ProjectViewView extends Vue {
} else {
// actually, axios throws an error on 404 so we probably never get here
logger.error("Error getting project:", resp);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "There was a problem getting that project.",
},
5000,
this.notify.error(
"There was a problem getting that project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
logger.error("Error retrieving project:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving that project.",
},
5000,
this.notify.error(
"Something went wrong retrieving that project.",
TIMEOUTS.LONG,
);
}
@ -944,26 +926,16 @@ export default class ProjectViewView extends Vue {
this.givesToThis = this.givesToThis.concat(resp.data.data);
this.givesHitLimit = resp.data.hitLimit;
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to retrieve more gives to this project.",
},
5000,
this.notify.error(
"Failed to retrieve more gives to this project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
const serverError = error as AxiosError;
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving more gives to this project.",
},
5000,
this.notify.error(
"Something went wrong retrieving more gives to this project.",
TIMEOUTS.LONG,
);
logger.error(
"Something went wrong retrieving more gives to this project:",
@ -1003,26 +975,16 @@ export default class ProjectViewView extends Vue {
);
this.givesProvidedByHitLimit = resp.data.hitLimit;
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to retrieve gives that were provided by this project.",
},
5000,
this.notify.error(
"Failed to retrieve gives that were provided by this project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
const serverError = error as AxiosError;
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving gives that were provided by this project.",
},
5000,
this.notify.error(
"Something went wrong retrieving gives that were provided by this project.",
TIMEOUTS.LONG,
);
logger.error(
"Something went wrong retrieving gives that were provided by this project:",
@ -1059,26 +1021,16 @@ export default class ProjectViewView extends Vue {
this.offersToThis = this.offersToThis.concat(resp.data.data);
this.offersHitLimit = resp.data.hitLimit;
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to retrieve more offers to this project.",
},
5000,
this.notify.error(
"Failed to retrieve more offers to this project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
const serverError = error as AxiosError;
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving more offers to this project.",
},
5000,
this.notify.error(
"Something went wrong retrieving more offers to this project.",
TIMEOUTS.LONG,
);
logger.error(
"Something went wrong retrieving more offers to this project:",
@ -1115,26 +1067,16 @@ export default class ProjectViewView extends Vue {
this.fulfillersToThis = this.fulfillersToThis.concat(resp.data.data);
this.fulfillersToHitLimit = resp.data.hitLimit;
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to retrieve more plans that fullfill this project.",
},
5000,
this.notify.error(
"Failed to retrieve more plans that fullfill this project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
const serverError = error as AxiosError;
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving more plans that fulfull this project.",
},
5000,
this.notify.error(
"Something went wrong retrieving more plans that fulfull this project.",
TIMEOUTS.LONG,
);
logger.error(
"Something went wrong retrieving more plans that fulfill this project:",
@ -1162,26 +1104,16 @@ export default class ProjectViewView extends Vue {
if (resp.status === 200) {
this.fulfilledByThis = resp.data.data;
} else {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to retrieve plans fulfilled by this project.",
},
5000,
this.notify.error(
"Failed to retrieve plans fulfilled by this project.",
TIMEOUTS.LONG,
);
}
} catch (error: unknown) {
const serverError = error as AxiosError;
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Something went wrong retrieving plans fulfilled by this project.",
},
5000,
this.notify.error(
"Something went wrong retrieving plans fulfilled by this project.",
TIMEOUTS.LONG,
);
logger.error(
"Error retrieving plans fulfilled by this project:",
@ -1444,14 +1376,9 @@ export default class ProjectViewView extends Vue {
this.axios,
);
if (result.success) {
this.$notify(
{
group: "alert",
type: "success",
title: "Success",
text: "Confirmation submitted.",
},
5000,
this.notify.success(
"Confirmation submitted.",
TIMEOUTS.LONG,
);
this.recentlyCheckedAndUnconfirmableJwts = [
...this.recentlyCheckedAndUnconfirmableJwts,
@ -1462,14 +1389,9 @@ export default class ProjectViewView extends Vue {
const message =
(result.error as string) ||
"There was a problem submitting the confirmation.";
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: message,
},
5000,
this.notify.error(
message,
TIMEOUTS.LONG,
);
}
}
@ -1521,14 +1443,9 @@ export default class ProjectViewView extends Vue {
}
} catch (error) {
logger.error("Error loading totals:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to load totals for this project.",
},
5000,
this.notify.error(
"Failed to load totals for this project.",
TIMEOUTS.LONG,
);
} finally {
this.loadingTotals = false;

30
src/views/RecentOffersToUserProjectsView.vue

@ -84,7 +84,6 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts";
import { Router } from "vue-router";
import { OfferToPlanSummaryRecord } from "../interfaces";
@ -95,13 +94,17 @@ import {
} from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
@Component({
components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav },
mixins: [PlatformServiceMixin],
})
export default class RecentOffersToUserView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
allContacts: Array<Contact> = [];
allMyDids: string[] = [];
@ -116,20 +119,16 @@ export default class RecentOffersToUserView extends Vue {
displayAmount = displayAmount;
async created() {
this.notify = createNotifyHelpers(this.$notify);
try {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await this.$accountSettings();
this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserProjectsJwtId =
settings.lastAckedOfferToUserProjectsJwtId || "";
const contactQueryResult =
await PlatformServiceFactory.getInstance().dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQueryResult,
) as unknown as Contact[];
this.allContacts = await this.$getAllContacts();
this.allMyDids = await retrieveAccountDids();
@ -146,14 +145,9 @@ export default class RecentOffersToUserView extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings & contacts:", err);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: err.message || "There was an error retrieving your activity.",
},
5000,
this.notify.error(
err.message || "There was an error retrieving your activity.",
TIMEOUTS.LONG,
);
}
}

30
src/views/RecentOffersToUserView.vue

@ -77,7 +77,6 @@ import EntityIcon from "../components/EntityIcon.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts";
import { OfferSummaryRecord } from "../interfaces";
import {
@ -87,13 +86,17 @@ import {
} from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
@Component({
components: { EntityIcon, GiftedDialog, InfiniteScroll, QuickNav },
mixins: [PlatformServiceMixin],
})
export default class RecentOffersToUserView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
activeDid = "";
allContacts: Array<Contact> = [];
allMyDids: string[] = [];
@ -108,19 +111,15 @@ export default class RecentOffersToUserView extends Vue {
displayAmount = displayAmount;
async created() {
this.notify = createNotifyHelpers(this.$notify);
try {
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await this.$accountSettings();
this.apiServer = settings.apiServer || "";
this.activeDid = settings.activeDid || "";
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || "";
const contactQueryResult =
await PlatformServiceFactory.getInstance().dbQuery(
"SELECT * FROM contacts",
);
this.allContacts = databaseUtil.mapQueryResultToValues(
contactQueryResult,
) as unknown as Contact[];
this.allContacts = await this.$getAllContacts();
this.allMyDids = await retrieveAccountDids();
@ -137,14 +136,9 @@ export default class RecentOffersToUserView extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
logger.error("Error retrieving settings & contacts:", err);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: err.message || "There was an error retrieving your activity.",
},
5000,
this.notify.error(
err.message || "There was an error retrieving your activity.",
TIMEOUTS.LONG,
);
}
}

48
src/views/ShareMyContactInfoView.vue

@ -54,6 +54,7 @@ import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { Settings } from "@/db/tables/settings";
import { Account } from "@/db/tables/accounts";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
// Constants for magic numbers
const NOTIFICATION_TIMEOUTS = {
@ -74,6 +75,8 @@ export default class ShareMyContactInfoView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
// Component state
isLoading = false;
@ -81,6 +84,7 @@ export default class ShareMyContactInfoView extends Vue {
* Main share functionality - orchestrates the contact sharing process
*/
async onClickShare(): Promise<void> {
this.notify = createNotifyHelpers(this.$notify);
this.isLoading = true;
try {
@ -149,27 +153,17 @@ export default class ShareMyContactInfoView extends Vue {
* Show success notifications after copying
*/
private async showSuccessNotifications(): Promise<void> {
this.$notify(
{
group: "alert",
type: "info",
title: "Copied",
text: "Your contact info was copied to the clipboard. Have them click on it, or paste it in the box on their 'Contacts' screen.",
},
NOTIFICATION_TIMEOUTS.COPY_SUCCESS,
this.notify.copied(
"contact info",
TIMEOUTS.LONG,
);
const numContacts = await this.$contactCount();
if (numContacts > 0) {
setTimeout(() => {
this.$notify(
{
group: "alert",
type: "success",
title: "Share Other Contacts",
text: "You may want to share some of your contacts with them. Select them below to copy and send.",
},
NOTIFICATION_TIMEOUTS.SHARE_CONTACTS,
this.notify.success(
"You may want to share some of your contacts with them. Select them below to copy and send.",
TIMEOUTS.VERY_LONG,
);
}, DELAYS.SHARE_CONTACTS_DELAY);
}
@ -186,14 +180,9 @@ export default class ShareMyContactInfoView extends Vue {
* Show account not found error
*/
private showAccountError(): void {
this.$notify(
{
group: "alert",
type: "error",
title: "Error",
text: "No account was found for the active DID.",
},
NOTIFICATION_TIMEOUTS.ERROR,
this.notify.error(
"No account was found for the active DID.",
TIMEOUTS.LONG,
);
}
@ -201,14 +190,9 @@ export default class ShareMyContactInfoView extends Vue {
* Show generic error notification
*/
private showGenericError(): void {
this.$notify(
{
group: "alert",
type: "error",
title: "Error",
text: "There was a problem sharing your contact information. Please try again.",
},
NOTIFICATION_TIMEOUTS.ERROR,
this.notify.error(
"There was a problem sharing your contact information. Please try again.",
TIMEOUTS.LONG,
);
}
}

Loading…
Cancel
Save