Compare commits

...

15 Commits

Author SHA1 Message Date
6482cfa6a3 fix: fix the claim-add-raw view to work with axios 2025-09-08 08:41:35 -06:00
d3c6f0ec27 chore: bump iOS project file to 1.0.10, too 2025-08-25 08:53:26 -06:00
3ea4dd6f9d chore: bump version to 1.0.10 2025-08-25 08:49:03 -06:00
0f35b16ddb feat: for confirm list, allow to see 30 minutes before meeting start 2025-08-25 08:47:15 -06:00
61370ce0ad chore: bump version and add "-beta" 2025-08-20 21:47:31 -06:00
b3e342c733 chore: Bump to version 1.0.9 build 43 2025-08-20 21:46:38 -06:00
3c463b1a2a chore: Bump to version 1.0.8 build 42. 2025-08-20 08:43:35 -06:00
de476210c5 fix: Fix onboard-meeting-members deep link with groupId. 2025-08-20 08:42:43 -06:00
ff61a0bdf3 chore: Bump to v 1.0.6 build 39 2025-08-10 18:37:45 -06:00
e0b9481be5 fix: Fix error with deep links trying to parse empty query parameters. 2025-08-10 18:37:07 -06:00
bcbb80e034 bump version and add "-beta" 2025-07-25 06:04:00 -06:00
64f24dc473 bump to version 1.0.5 and build 38 2025-07-25 06:02:59 -06:00
6ddde21a86 Merge pull request 'fix problem with repeated bad stringifies of contactMethods on contact export/import' (#148) from fix-contact-import-export into master
Reviewed-on: #148
2025-07-24 21:33:47 -04:00
fd0026ac2d fix problem with repeated bad stringifies of contactMethods on contact export/import 2025-07-22 15:51:17 -06:00
3fce10ae98 bump version and add "-beta", and update commit hashes in changelog 2025-07-22 11:02:12 -06:00
17 changed files with 1267 additions and 3501 deletions

View File

@@ -364,7 +364,7 @@ Prerequisites: macOS with Xcode installed
4. Bump the version to match Android & package.json: 4. Bump the version to match Android & package.json:
``` ```
cd ios/App && xcrun agvtool new-version 37 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.4;/g" App.xcodeproj/project.pbxproj && cd - cd ios/App && xcrun agvtool new-version 44 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.10;/g" App.xcodeproj/project.pbxproj && cd -
# Unfortunately this edits Info.plist directly. # Unfortunately this edits Info.plist directly.
#xcrun agvtool new-marketing-version 0.4.5 #xcrun agvtool new-marketing-version 0.4.5
``` ```

View File

@@ -6,12 +6,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.4] - 2025.07.20 ## [1.0.10] - 2025.08.25
### Fixed
- Now shows confirmable claims 30 minutes before meeting starts
## [1.0.9] - 2025.08.20
### Fixed
- Deep link errors for meeting members
## [1.0.6] - 2025.08.09
### Fixed
- Deep link errors where none would validate
## [1.0.5] - 2025.07.24
### Fixed
- Export & import of contacts corrupted contact methods
## [1.0.4] - 2025.07.20 - 002f2407208d56cc59c0aa7c880535ae4cbace8b
### Fixed ### Fixed
- Deep link for invite-one-accept - Deep link for invite-one-accept
## [1.0.3] - 2025.07.12 ## [1.0.3] - 2025.07.12 - a9a8ba217cd6015321911e98e6843e988dc2c4ae
### Changed ### Changed
- Photo is pinned to profile mode - Photo is pinned to profile mode
### Fixed ### Fixed

View File

@@ -31,8 +31,8 @@ android {
applicationId "app.timesafari.app" applicationId "app.timesafari.app"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 37 versionCode 44
versionName "1.0.4" versionName "1.0.10"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions { aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

View File

@@ -403,7 +403,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37; CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = GM3FS5JQPH; DEVELOPMENT_TEAM = GM3FS5JQPH;
ENABLE_APP_SANDBOX = NO; ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
@@ -413,7 +413,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.4; MARKETING_VERSION = 1.0.10;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = app.timesafari; PRODUCT_BUNDLE_IDENTIFIER = app.timesafari;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -430,7 +430,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 37; CURRENT_PROJECT_VERSION = 44;
DEVELOPMENT_TEAM = GM3FS5JQPH; DEVELOPMENT_TEAM = GM3FS5JQPH;
ENABLE_APP_SANDBOX = NO; ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
@@ -440,7 +440,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.4; MARKETING_VERSION = 1.0.10;
PRODUCT_BUNDLE_IDENTIFIER = app.timesafari; PRODUCT_BUNDLE_IDENTIFIER = app.timesafari;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";

4596
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "timesafari", "name": "timesafari",
"version": "1.0.4", "version": "1.0.10",
"description": "Time Safari Application", "description": "Time Safari Application",
"author": { "author": {
"name": "Time Safari Team" "name": "Time Safari Team"

View File

@@ -60,9 +60,11 @@ backup and database export, with platform-specific download instructions. * *
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator"; import { Component, Prop, Vue } from "vue-facing-decorator";
import * as R from "ramda";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface } from "../constants/app";
import { Contact } from "../db/tables/contacts"; import { Contact, ContactMaybeWithJsonStrings, ContactMethod } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@@ -72,6 +74,7 @@ import {
PlatformCapabilities, PlatformCapabilities,
} from "../services/PlatformService"; } from "../services/PlatformService";
import { contactsToExportJson } from "../libs/util"; import { contactsToExportJson } from "../libs/util";
import { parseJsonField } from "../db/databaseUtil";
/** /**
* @vue-component * @vue-component
@@ -133,13 +136,13 @@ export default class DataExportSection extends Vue {
*/ */
public async exportDatabase() { public async exportDatabase() {
try { try {
let allContacts: Contact[] = []; let allDbContacts: ContactMaybeWithJsonStrings[] = [];
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const result = await platformService.dbQuery(`SELECT * FROM contacts`); const result = await platformService.dbQuery(`SELECT * FROM contacts`);
if (result) { if (result) {
allContacts = databaseUtil.mapQueryResultToValues( allDbContacts = databaseUtil.mapQueryResultToValues(
result, result,
) as unknown as Contact[]; ) as unknown as ContactMaybeWithJsonStrings[];
} }
// if (USE_DEXIE_DB) { // if (USE_DEXIE_DB) {
// await db.open(); // await db.open();
@@ -147,6 +150,19 @@ export default class DataExportSection extends Vue {
// } // }
// Convert contacts to export format // Convert contacts to export format
const allContacts: Contact[] = allDbContacts.map((contact) => {
// first remove the contactMethods field, mostly to cast to a clear type (that will end up with JSON objects)
const exContact: Contact = R.omit(
["contactMethods"],
contact,
);
// now add contactMethods as a true array of ContactMethod objects
exContact.contactMethods = contact.contactMethods
? parseJsonField(contact.contactMethods, [] as Array<ContactMethod>)
: undefined;
return exContact;
});
const exportData = contactsToExportJson(allContacts); const exportData = contactsToExportJson(allContacts);
const jsonStr = JSON.stringify(exportData, null, 2); const jsonStr = JSON.stringify(exportData, null, 2);
const blob = new Blob([jsonStr], { type: "application/json" }); const blob = new Blob([jsonStr], { type: "application/json" });

View File

@@ -30,6 +30,17 @@ export type ContactWithJsonStrings = Omit<Contact, "contactMethods"> & {
contactMethods?: string; contactMethods?: string;
}; };
/**
* This is for those cases (eg. with a DB) where field values may be all primitives or may be JSON values.
* See src/db/databaseUtil.ts parseJsonField for more details.
*
* This is so that we can reuse most of the type and don't have to maintain another copy.
* Another approach uses typescript conditionals: https://chatgpt.com/share/6855cdc3-ab5c-8007-8525-726612016eb2
*/
export type ContactMaybeWithJsonStrings = Omit<Contact, "contactMethods"> & {
contactMethods?: string | Array<ContactMethod>;
};
export const ContactSchema = { export const ContactSchema = {
contacts: "&did, name", // no need to key by other things contacts: "&did, name", // no need to key by other things
}; };

View File

@@ -28,12 +28,11 @@
import { z } from "zod"; import { z } from "zod";
// Parameter validation schemas for each route type // Parameter validation schemas for each route type
export const deepLinkSchemas = { export const deepLinkPathSchemas = {
claim: z.object({ claim: z.object({
id: z.string(), id: z.string(),
}), }),
"claim-add-raw": z.object({ "claim-add-raw": z.object({
id: z.string(),
claim: z.string().optional(), claim: z.string().optional(),
claimJwtId: z.string().optional(), claimJwtId: z.string().optional(),
}), }),
@@ -61,7 +60,7 @@ export const deepLinkSchemas = {
jwt: z.string().optional(), jwt: z.string().optional(),
}), }),
"onboard-meeting-members": z.object({ "onboard-meeting-members": z.object({
id: z.string(), groupId: z.string(),
}), }),
project: z.object({ project: z.object({
id: z.string(), id: z.string(),
@@ -71,6 +70,17 @@ export const deepLinkSchemas = {
}), }),
}; };
export const deepLinkQuerySchemas = {
"onboard-meeting-members": z.object({
password: z.string(),
}),
};
// Add a union type of all valid route paths
export const VALID_DEEP_LINK_ROUTES = Object.keys(
deepLinkPathSchemas,
) as readonly (keyof typeof deepLinkPathSchemas)[];
// Create a type from the array // Create a type from the array
export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number]; export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number];
@@ -81,14 +91,13 @@ export const baseUrlSchema = z.object({
queryParams: z.record(z.string()).optional(), queryParams: z.record(z.string()).optional(),
}); });
// Add a union type of all valid route paths // export type DeepLinkPathParams = {
export const VALID_DEEP_LINK_ROUTES = Object.keys( // [K in keyof typeof deepLinkPathSchemas]: z.infer<(typeof deepLinkPathSchemas)[K]>;
deepLinkSchemas, // };
) as readonly (keyof typeof deepLinkSchemas)[];
export type DeepLinkParams = { // export type DeepLinkQueryParams = {
[K in keyof typeof deepLinkSchemas]: z.infer<(typeof deepLinkSchemas)[K]>; // [K in keyof typeof deepLinkQuerySchemas]: z.infer<(typeof deepLinkQuerySchemas)[K]>;
}; // };
export interface DeepLinkError extends Error { export interface DeepLinkError extends Error {
code: string; code: string;

View File

@@ -214,13 +214,13 @@ const testRecursivelyOnStrings = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function containsHiddenDid(obj: any) { export function containsHiddenDid(obj: any) {
return testRecursivelyOnStrings(isHiddenDid, obj); return testRecursivelyOnStrings(obj, isHiddenDid);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const containsNonHiddenDid = (obj: any) => { export const containsNonHiddenDid = (obj: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
return testRecursivelyOnStrings((s: any) => isDid(s) && !isHiddenDid(s), obj); return testRecursivelyOnStrings(obj, (s: any) => isDid(s) && !isHiddenDid(s));
}; };
export function stripEndorserPrefix(claimId: string) { export function stripEndorserPrefix(claimId: string) {

View File

@@ -17,7 +17,7 @@ import {
updateDefaultSettings, updateDefaultSettings,
} from "../db/index"; } from "../db/index";
import { Account, AccountEncrypted } from "../db/tables/accounts"; import { Account, AccountEncrypted } from "../db/tables/accounts";
import { Contact, ContactWithJsonStrings } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { DEFAULT_PASSKEY_EXPIRATION_MINUTES } from "../db/tables/settings"; import { DEFAULT_PASSKEY_EXPIRATION_MINUTES } from "../db/tables/settings";
import { import {
@@ -966,31 +966,19 @@ export interface DatabaseExport {
} }
/** /**
* Converts an array of contacts to the standardized database export JSON format. * Converts an array of contacts to the export JSON format.
* This format is used for data migration and backup purposes. * This format is used for data migration and backup purposes.
* *
* @param contacts - Array of Contact objects to convert * @param contacts - Array of Contact objects to convert
* @returns DatabaseExport object in the standardized format * @returns DatabaseExport object in the standardized format
*/ */
export const contactsToExportJson = (contacts: Contact[]): DatabaseExport => { export const contactsToExportJson = (contacts: Contact[]): DatabaseExport => {
// Convert each contact to a plain object and ensure all fields are included
const rows = contacts.map((contact) => {
const exContact: ContactWithJsonStrings = R.omit(
["contactMethods"],
contact,
);
exContact.contactMethods = contact.contactMethods
? JSON.stringify(contact.contactMethods, [])
: undefined;
return exContact;
});
return { return {
data: { data: {
data: [ data: [
{ {
tableName: "contacts", tableName: "contacts",
rows, rows: contacts,
}, },
], ],
}, },

View File

@@ -47,10 +47,11 @@ import { Router } from "vue-router";
import { z } from "zod"; import { z } from "zod";
import { import {
deepLinkSchemas, deepLinkPathSchemas,
baseUrlSchema, baseUrlSchema,
routeSchema, routeSchema,
DeepLinkRoute, DeepLinkRoute,
deepLinkQuerySchemas,
} from "../interfaces/deepLinks"; } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import type { DeepLinkError } from "../interfaces/deepLinks"; import type { DeepLinkError } from "../interfaces/deepLinks";
@@ -74,7 +75,7 @@ function getFirstKeyFromZodObject(
* because "router.replace" expects the right parameter name for the route. * because "router.replace" expects the right parameter name for the route.
*/ */
export const ROUTE_MAP: Record<string, { name: string; paramKey?: string }> = export const ROUTE_MAP: Record<string, { name: string; paramKey?: string }> =
Object.entries(deepLinkSchemas).reduce( Object.entries(deepLinkPathSchemas).reduce(
(acc, [routeName, schema]) => { (acc, [routeName, schema]) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject<any>); const paramKey = getFirstKeyFromZodObject(schema as z.ZodObject<any>);
@@ -199,17 +200,22 @@ export class DeepLinkHandler {
} }
// Continue with parameter validation as before... // Continue with parameter validation as before...
const schema = deepLinkSchemas[path as keyof typeof deepLinkSchemas]; const pathSchema = deepLinkPathSchemas[path as keyof typeof deepLinkPathSchemas];
const querySchema = deepLinkQuerySchemas[path as keyof typeof deepLinkQuerySchemas];
let validatedParams, validatedQuery; let validatedPathParams: Record<string, string> = {};
let validatedQueryParams: Record<string, string> = {};
try { try {
validatedParams = await schema.parseAsync(params); if (pathSchema) {
validatedQuery = await schema.parseAsync(query); validatedPathParams = await pathSchema.parseAsync(params);
}
if (querySchema) {
validatedQueryParams = await querySchema.parseAsync(query);
}
} catch (error) { } catch (error) {
// For parameter validation errors, provide specific error feedback // For parameter validation errors, provide specific error feedback
logConsoleAndDb( logConsoleAndDb(
`[DeepLink] Invalid parameters for route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`, `[DeepLink] Invalid parameters for route name ${routeName} for path: ${path} ... with error: ${JSON.stringify(error)} ... with params: ${JSON.stringify(params)} ... and query: ${JSON.stringify(query)}`,
true,
); );
await this.router.replace({ await this.router.replace({
name: "deep-link-error", name: "deep-link-error",
@@ -229,23 +235,22 @@ export class DeepLinkHandler {
try { try {
await this.router.replace({ await this.router.replace({
name: routeName, name: routeName,
params: validatedParams, params: validatedPathParams,
query: validatedQuery, query: validatedQueryParams
}); });
} catch (error) { } catch (error) {
logConsoleAndDb( logConsoleAndDb(
`[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedParams)} ... and validated query: ${JSON.stringify(validatedQuery)}`, `[DeepLink] Error routing to route name ${routeName} for path: ${path}: ${JSON.stringify(error)} ... with validated params: ${JSON.stringify(validatedPathParams)} ... and query: ${JSON.stringify(validatedQueryParams)}`,
true,
); );
// For parameter validation errors, provide specific error feedback // For parameter validation errors, provide specific error feedback
await this.router.replace({ await this.router.replace({
name: "deep-link-error", name: "deep-link-error",
params: validatedParams, params: validatedPathParams,
query: { query: {
originalPath: path, originalPath: path,
errorCode: "ROUTING_ERROR", errorCode: "ROUTING_ERROR",
errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`, errorMessage: `Error routing to ${routeName}: ${JSON.stringify(error)}`,
...validatedQuery, ...validatedQueryParams,
}, },
}); });
} }

View File

@@ -1154,6 +1154,7 @@ export default class AccountViewView extends Vue {
} catch (error) { } catch (error) {
if (error.status === 404) { if (error.status === 404) {
// this is ok: the profile is not yet created // this is ok: the profile is not yet created
logger.info("Note that axios may have logged an error but it just doesn't exist.");
} else { } else {
databaseUtil.logConsoleAndDb( databaseUtil.logConsoleAndDb(
"Error loading profile: " + errorStringForLog(error), "Error loading profile: " + errorStringForLog(error),

View File

@@ -30,7 +30,6 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { AxiosInstance } from "axios";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface, USE_DEXIE_DB } from "../constants/app"; import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
@@ -54,7 +53,6 @@ export default class ClaimAddRawView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded; $route!: RouteLocationNormalizedLoaded;
$router!: Router; $router!: Router;
axios!: AxiosInstance;
accountIdentityStr: string = "null"; accountIdentityStr: string = "null";
activeDid = ""; activeDid = "";

View File

@@ -47,7 +47,7 @@ import { computed, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import { import {
VALID_DEEP_LINK_ROUTES, VALID_DEEP_LINK_ROUTES,
deepLinkSchemas, deepLinkPathSchemas,
} from "../interfaces/deepLinks"; } from "../interfaces/deepLinks";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@@ -56,7 +56,7 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
// an object with the route as the key and the first param name as the value // an object with the route as the key and the first param name as the value
const deepLinkSchemaKeys = Object.fromEntries( const deepLinkSchemaKeys = Object.fromEntries(
Object.entries(deepLinkSchemas).map(([route, schema]) => { Object.entries(deepLinkPathSchemas).map(([route, schema]) => {
const param = Object.keys(schema.shape)[0]; const param = Object.keys(schema.shape)[0];
return [route, param]; return [route, param];
}), }),

View File

@@ -117,6 +117,9 @@ export default class OnboardMeetingMembersView extends Vue {
this.isRegistered = settings.isRegistered || false; this.isRegistered = settings.isRegistered || false;
try { try {
if (!this.activeDid) { if (!this.activeDid) {
logConsoleAndDb(
"[OnboardMeetingMembersView] No active DID found, creating identity as fallback for meeting setup",
);
this.activeDid = await generateSaveAndActivateIdentity(); this.activeDid = await generateSaveAndActivateIdentity();
this.isRegistered = false; this.isRegistered = false;
} }

View File

@@ -221,7 +221,8 @@ export default class QuickActionBvcBeginView extends Vue {
} }
const eventStartDateObj = currentOrPreviousSat const eventStartDateObj = currentOrPreviousSat
.set({ weekday: 6 }) .set({ weekday: 6 })
.set({ hour: 9 }) .set({ hour: 8 })
.set({ minute: 30 }) // to catch if people put their claims 30 minutes early
.startOf("hour"); .startOf("hour");
// Hack, but full ISO pushes the length to 340 which crashes verifyJWT! // Hack, but full ISO pushes the length to 340 which crashes verifyJWT!