You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

243 lines
7.7 KiB

<template>
<QuickNav selected="Profile"></QuickNav>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<router-link
:to="{ name: 'account' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
Switch Identity
</h1>
</div>
<!-- Identity List -->
<!-- Current Identity - Display First! -->
<div
v-if="activeDid && !activeDidInIdentities"
class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-4"
>
<font-awesome
icon="circle-check"
class="fa-fw text-red-600 text-xl mr-3"
></font-awesome>
<div class="text-sm text-slate-500">
<div class="overflow-hidden truncate">
<b>ID:</b> <code>{{ activeDid }}</code>
</div>
<b
>There is a data corruption error: this identity is selected but it is
not in storage. You cannot send any more claims with this identity
until you import the seed again. This may require reinstalling the
app; if you know how, you can also clear out the TimeSafariAccounts
IndexedDB. Be sure to back up all your Settings & Contacts first.</b
>
</div>
</div>
<!-- Other Identity/ies -->
<ul class="mb-4">
<li v-for="ident in otherIdentities" :key="ident.did">
<div class="flex items-center justify-between mb-2">
<div
:class="identityListItemClasses"
@click="switchAccount(ident.did)"
>
<font-awesome
v-if="ident.did === activeDid"
icon="circle-check"
class="fa-fw text-blue-600 text-xl mr-3"
/>
<font-awesome
v-else
icon="circle"
class="fa-fw text-slate-400 text-xl mr-3"
/>
<span class="flex-grow overflow-hidden">
<div class="text-sm text-slate-500 truncate">
<b>ID:</b> <code>{{ ident.did }}</code>
</div>
</span>
</div>
<div>
<font-awesome
v-if="ident.did === activeDid"
icon="trash-can"
class="text-slate-400 text-xl ml-2 mr-2 cursor-pointer"
@click="notifyCannotDelete()"
/>
<font-awesome
v-else
icon="trash-can"
class="text-red-600 text-xl ml-2 mr-2 cursor-pointer"
@click="deleteAccount(ident.id)"
/>
</div>
</div>
</li>
</ul>
<!-- Actions -->
<!-- id used by puppeteer test script -->
<router-link
id="start-link"
:to="{ name: 'start' }"
:class="primaryButtonClasses"
>
Add Another Identity&hellip;
</router-link>
<a
href="#"
:class="secondaryButtonClasses"
@click="switchAccount(undefined)"
>
No Identity
</a>
</section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_ERROR_LOADING_ACCOUNTS,
NOTIFY_CANNOT_DELETE_ACTIVE_IDENTITY,
NOTIFY_DELETE_IDENTITY_CONFIRM,
} from "@/constants/notifications";
import { Account } from "@/db/tables/accounts";
@Component({
components: { QuickNav },
mixins: [PlatformServiceMixin],
})
export default class IdentitySwitcherView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
public activeDid = "";
public activeDidInIdentities = false;
public apiServer = "";
public apiServerInput = "";
public otherIdentities: Array<{ id: string; did: string }> = [];
/**
* Vue lifecycle hook - Initialize notification helpers
*/
mounted() {
this.notify = createNotifyHelpers(this.$notify);
}
// =================================================
// COMPUTED PROPERTIES - Template Logic Streamlining
// =================================================
/**
* CSS classes for primary action buttons (Add Another Identity)
* Reduces template complexity for gradient button styling
*/
get primaryButtonClasses(): string {
return "block text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md mb-2";
}
/**
* CSS classes for secondary action buttons (No Identity)
* Reduces template complexity for gradient button styling
*/
get secondaryButtonClasses(): string {
return "block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-8";
}
/**
* CSS classes for identity list items
* Reduces template complexity for repeated list item styling
*/
get identityListItemClasses(): string {
return "flex flex-grow items-center bg-slate-100 rounded-md px-4 py-3 mb-2 truncate cursor-pointer";
}
// =================================================
// HELPER METHODS - Template Logic Streamlining
// =================================================
/**
* Formats account data for display in the identity list
* Consolidates account processing logic from template
* @param account - Account object from database
* @returns Formatted account object for display
*/
formatAccountForDisplay(account: Account): { id: string; did: string } {
return {
id: (account.id ?? 0).toString(),
did: account.did,
};
}
// =================================================
// COMPONENT METHODS
// =================================================
async created() {
try {
const settings = await this.$accountSettings();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
this.apiServerInput = settings.apiServer || "";
const accounts = await retrieveAllAccountsMetadata();
for (let n = 0; n < accounts.length; n++) {
const acct = accounts[n];
this.otherIdentities.push(this.formatAccountForDisplay(acct));
if (acct.did && this.activeDid === acct.did) {
this.activeDidInIdentities = true;
}
}
} catch (err) {
this.notify.error(NOTIFY_ERROR_LOADING_ACCOUNTS.message, TIMEOUTS.LONG);
logger.error("Telling user to clear cache at page create because:", err);
}
}
async switchAccount(did?: string) {
await this.$saveSettings({ activeDid: did });
this.$router.push({ name: "account" });
}
async deleteAccount(id: string) {
this.$notify(
{
group: "modal",
type: "confirm",
title: NOTIFY_DELETE_IDENTITY_CONFIRM.title,
text: NOTIFY_DELETE_IDENTITY_CONFIRM.text,
onYes: async () => {
await this.$exec(`DELETE FROM accounts WHERE id = ?`, [id]);
this.otherIdentities = this.otherIdentities.filter(
(ident) => ident.id !== id,
);
},
},
-1,
);
}
notifyCannotDelete() {
this.notify.warning(
NOTIFY_CANNOT_DELETE_ACTIVE_IDENTITY.message,
TIMEOUTS.SHORT,
);
}
}
</script>