Merge branch 'master' into contact-gifting-current-user

This commit is contained in:
Jose Olarte III
2025-08-26 16:51:09 +08:00
241 changed files with 20051 additions and 3992 deletions

View File

@@ -86,33 +86,14 @@ Raymer * @version 1.0.0 */
Identity creation is now handled by router navigation guard.
-->
<div class="mb-4">
<div
<RegistrationNotice
v-if="!isUserRegistered"
id="noticeSomeoneMustRegisterYou"
class="bg-amber-200 rounded-md overflow-hidden text-center px-4 py-3 mb-4"
>
To share, someone must register you.
<div class="block text-center">
<button
class="text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mt-2 px-2 py-3 rounded-md"
@click="showNameThenIdDialog()"
>
Show them {{ PASSKEYS_ENABLED ? "default" : "your" }} identifier
info
</button>
</div>
<UserNameDialog ref="userNameDialog" />
<div class="flex justify-end w-full">
<router-link
:to="{ name: 'start' }"
class="block text-right text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mt-2 px-2 py-3 rounded-md"
>
See advanced options
</router-link>
</div>
</div>
:passkeys-enabled="PASSKEYS_ENABLED"
:given-name="givenName"
message="To share, someone must register you."
/>
<div v-else id="sectionRecordSomethingGiven">
<div v-if="isUserRegistered" id="sectionRecordSomethingGiven">
<!-- Record Quick-Action -->
<div class="mb-6">
<div class="flex gap-2 items-center mb-2">
@@ -252,8 +233,6 @@ Raymer * @version 1.0.0 */
</div>
</section>
<ChoiceButtonDialog ref="choiceButtonDialog" />
<ImageViewer v-model:is-open="isImageViewerOpen" :image-url="selectedImage" />
</template>
@@ -261,7 +240,6 @@ Raymer * @version 1.0.0 */
import { UAParser } from "ua-parser-js";
import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";
import { Capacitor } from "@capacitor/core";
//import App from "../App.vue";
import EntityIcon from "../components/EntityIcon.vue";
@@ -272,10 +250,9 @@ import InfiniteScroll from "../components/InfiniteScroll.vue";
import OnboardingDialog from "../components/OnboardingDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import UserNameDialog from "../components/UserNameDialog.vue";
import ChoiceButtonDialog from "../components/ChoiceButtonDialog.vue";
import ImageViewer from "../components/ImageViewer.vue";
import ActivityListItem from "../components/ActivityListItem.vue";
import RegistrationNotice from "../components/RegistrationNotice.vue";
import {
AppString,
NotificationIface,
@@ -384,12 +361,11 @@ interface FeedError {
GiftedPrompts,
InfiniteScroll,
OnboardingDialog,
ChoiceButtonDialog,
QuickNav,
TopMessage,
UserNameDialog,
ImageViewer,
ActivityListItem,
RegistrationNotice,
},
mixins: [PlatformServiceMixin],
})
@@ -477,7 +453,7 @@ export default class HomeView extends Vue {
// Re-initialize identity with new settings (loads settings internally)
await this.initializeIdentity();
} else {
logger.info(
logger.debug(
"[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization",
);
}
@@ -757,17 +733,34 @@ export default class HomeView extends Vue {
* Called by FeedFilters component when filters change
*/
async reloadFeedOnChange() {
const settings = await this.$accountSettings(this.activeDid, {
filterFeedByVisible: false,
filterFeedByNearby: false,
logger.debug("[HomeView] 🔄 reloadFeedOnChange() called - refreshing feed");
// Get current settings without overriding with defaults
const settings = await this.$accountSettings(this.activeDid);
logger.debug("[HomeView] 📊 Current filter settings:", {
filterFeedByVisible: settings.filterFeedByVisible,
filterFeedByNearby: settings.filterFeedByNearby,
searchBoxes: settings.searchBoxes?.length || 0,
});
this.isFeedFilteredByVisible = !!settings.filterFeedByVisible;
this.isFeedFilteredByNearby = !!settings.filterFeedByNearby;
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
logger.debug("[HomeView] 🎯 Updated filter states:", {
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
});
this.feedData = [];
this.feedPreviousOldestId = undefined;
logger.debug("[HomeView] 🧹 Cleared feed data, calling updateAllFeed()");
await this.updateAllFeed();
logger.debug("[HomeView] ✅ Feed refresh completed");
}
/**
@@ -846,6 +839,14 @@ export default class HomeView extends Vue {
* - this.feedLastViewedClaimId (via updateFeedLastViewedId)
*/
async updateAllFeed() {
logger.debug("[HomeView] 🚀 updateAllFeed() called", {
isFeedLoading: this.isFeedLoading,
currentFeedDataLength: this.feedData.length,
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
});
this.isFeedLoading = true;
let endOfResults = true;
@@ -854,21 +855,37 @@ export default class HomeView extends Vue {
this.apiServer,
this.feedPreviousOldestId,
);
logger.debug("[HomeView] 📡 Retrieved gives from API", {
resultsCount: results.data.length,
endOfResults,
});
if (results.data.length > 0) {
endOfResults = false;
// gather any contacts that user has blocked from view
await this.processFeedResults(results.data);
await this.updateFeedLastViewedId(results.data);
logger.debug("[HomeView] 📝 Processed feed results", {
processedCount: this.feedData.length,
});
}
} catch (e) {
logger.error("[HomeView] ❌ Error in updateAllFeed:", e);
this.handleFeedError(e);
}
if (this.feedData.length === 0 && !endOfResults) {
logger.debug("[HomeView] 🔄 No results after filtering, retrying...");
await this.updateAllFeed();
}
this.isFeedLoading = false;
logger.debug("[HomeView] ✅ updateAllFeed() completed", {
finalFeedDataLength: this.feedData.length,
isFeedLoading: this.isFeedLoading,
});
}
/**
@@ -893,12 +910,35 @@ export default class HomeView extends Vue {
* @param records Array of feed records to process
*/
private async processFeedResults(records: GiveSummaryRecord[]) {
logger.debug("[HomeView] 📝 Processing feed results:", {
inputRecords: records.length,
currentFilters: {
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByVisible,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
},
});
let processedCount = 0;
let filteredCount = 0;
for (const record of records) {
const processedRecord = await this.processRecord(record);
if (processedRecord) {
this.feedData.push(processedRecord);
processedCount++;
} else {
filteredCount++;
}
}
logger.debug("[HomeView] 📊 Feed processing results:", {
processed: processedCount,
filtered: filteredCount,
total: records.length,
finalFeedLength: this.feedData.length,
});
this.feedPreviousOldestId = records[records.length - 1].jwtId;
}
@@ -932,7 +972,7 @@ export default class HomeView extends Vue {
* - this.feedData (via createFeedRecord)
*
* @param record The record to process
* @returns Processed record with contact info if it passes filters, null otherwise
* @returns Processed record if it passes filters, null otherwise
*/
private async processRecord(
record: GiveSummaryRecord,
@@ -942,13 +982,28 @@ export default class HomeView extends Vue {
const recipientDid = this.extractRecipientDid(claim);
const fulfillsPlan = await this.getFulfillsPlan(record);
// Log record details for debugging
logger.debug("[HomeView] 🔍 Processing record:", {
recordId: record.jwtId,
hasFulfillsPlan: !!fulfillsPlan,
fulfillsPlanHandleId: record.fulfillsPlanHandleId,
filters: {
isAnyFeedFilterOn: this.isAnyFeedFilterOn,
isFeedFilteredByVisible: this.isFeedFilteredByNearby,
isFeedFilteredByNearby: this.isFeedFilteredByNearby,
},
});
if (!this.shouldIncludeRecord(record, fulfillsPlan)) {
logger.debug("[HomeView] ❌ Record filtered out:", record.jwtId);
return null;
}
const provider = this.extractProvider(claim);
const providedByPlan = await this.getProvidedByPlan(provider);
logger.debug("[HomeView] ✅ Record included:", record.jwtId);
return this.createFeedRecord(
record,
claim,
@@ -1097,6 +1152,22 @@ export default class HomeView extends Vue {
}
}
// Add debug logging for nearby filter
if (this.isFeedFilteredByNearby && record.fulfillsPlanHandleId) {
logger.debug("[HomeView] 🔍 Nearby filter check:", {
recordId: record.jwtId,
hasFulfillsPlan: !!fulfillsPlan,
hasLocation: !!(fulfillsPlan?.locLat && fulfillsPlan?.locLon),
location: fulfillsPlan
? { lat: fulfillsPlan.locLat, lon: fulfillsPlan.locLon }
: null,
inSearchBox: fulfillsPlan
? this.latLongInAnySearchBox(fulfillsPlan.locLat, fulfillsPlan.locLon)
: null,
finalResult: anyMatch,
});
}
return anyMatch;
}
@@ -1543,7 +1614,10 @@ export default class HomeView extends Vue {
* Called by template click handler
*/
openFeedFilters() {
(this.$refs.feedFilters as FeedFilters).open(this.reloadFeedOnChange);
(this.$refs.feedFilters as FeedFilters).open(
this.reloadFeedOnChange,
this.activeDid,
);
}
/**
@@ -1558,67 +1632,6 @@ export default class HomeView extends Vue {
return known ? "text-slate-500" : "text-slate-100";
}
/**
* Shows name input dialog if needed
*
* @public
* @callGraph
* Called by: Template
* Calls:
* - UserNameDialog.open()
* - promptForShareMethod()
*
* @chain
* Template -> showNameThenIdDialog() -> promptForShareMethod()
*
* @requires
* - this.$refs.userNameDialog
* - this.givenName
*/
showNameThenIdDialog() {
if (!this.givenName) {
(this.$refs.userNameDialog as UserNameDialog).open(() => {
this.promptForShareMethod();
});
} else {
this.promptForShareMethod();
}
}
/**
* Shows dialog for sharing method selection
*
* @internal
* @callGraph
* Called by: showNameThenIdDialog()
* Calls: ChoiceButtonDialog.open()
*
* @chain
* Template -> showNameThenIdDialog() -> promptForShareMethod()
*
* @requires
* - this.$refs.choiceButtonDialog
* - this.$router
*/
promptForShareMethod() {
(this.$refs.choiceButtonDialog as ChoiceButtonDialog).open({
title: "How can you share your info?",
text: "",
option1Text: "We are in a meeting together",
option2Text: "We are nearby with cameras",
option3Text: "We will share some other way",
onOption1: () => {
this.$router.push({ name: "onboard-meeting-list" });
},
onOption2: () => {
this.handleQRCodeClick();
},
onOption3: () => {
this.$router.push({ name: "share-my-contact-info" });
},
});
}
/**
* Opens image viewer dialog
*