Compare commits

...
8 Commits
15 changed files with 40 additions and 48 deletions
+6 -9
View File
@@ -63,13 +63,13 @@ Install dependencies:
* Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`. * Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`.
* Commit everything (since the commit hash is used the app).
* Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build` * Run a build to make sure package-lock version is updated, linting works, etc: `npm install && npm run build`
* Commit everything (since the commit hash is used the app).
* Put the commit hash in the changelog (which will help you remember to bump the version in the step later). * Put the commit hash in the changelog (which will help you remember to bump the version in the step later).
* Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 1.0.0 && git push origin 1.0.0`. * Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 1.0.2 && git push origin 1.0.2`.
* For test, build the app (because test server is not yet set up to build): * For test, build the app (because test server is not yet set up to build):
@@ -93,11 +93,11 @@ TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.
* `pkgx +npm sh` * `pkgx +npm sh`
* `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 1.0.0 && npm install && npm run build:web && cd -` * `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 1.0.2 && npm install && npm run build:web && cd -`
(The plain `npm run build:web` uses the .env.production file.) (The plain `npm run build:web` uses the .env.production file.)
* Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-1 && mv crowd-funder-for-time-pwa/dist time-safari/` * Back up the time-safari/dist folder & deploy: `mv time-safari/dist time-safari-dist-prev-2 && mv crowd-funder-for-time-pwa/dist time-safari/`
* Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, commit, and push. Also record what version is on production. * Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, commit, and push. Also record what version is on production.
@@ -362,12 +362,9 @@ 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 cd ios/App && xcrun agvtool new-version 35 && perl -p -i -e "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 1.0.2;/g" App.xcodeproj/project.pbxproj && cd -
xcrun agvtool new-version 34
# 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
cat App.xcodeproj/project.pbxproj | sed "s/MARKETING_VERSION = .*;/MARKETING_VERSION = 0.5.8;/g" > temp && mv temp App.xcodeproj/project.pbxproj
cd -
``` ```
5. Open the project in Xcode: 5. Open the project in Xcode:
+6 -1
View File
@@ -6,7 +6,12 @@ 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.2] - 2025.06.20 ## [Unreleased]
### Changed
- Photo is pinned to profile mode
## [1.0.2] - 2025.06.20 - 276e0a741bc327de3380c4e508cccb7fee58c06d
### Added ### Added
- Version on feed title - Version on feed title
+2 -2
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 34 versionCode 35
versionName "0.5.8" versionName "1.0.2"
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.
+1
View File
@@ -13,6 +13,7 @@
android:exported="true" android:exported="true"
android:label="@string/title_activity_main" android:label="@string/title_activity_main"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBarLaunch"> android:theme="@style/AppTheme.NoActionBarLaunch">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
+4 -4
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 = 34; CURRENT_PROJECT_VERSION = 35;
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 = 0.5.8; MARKETING_VERSION = 1.0.2;
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 = 34; CURRENT_PROJECT_VERSION = 35;
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 = 0.5.8; MARKETING_VERSION = 1.0.2;
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 = "";
-2
View File
@@ -37,8 +37,6 @@
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "timesafari", "name": "timesafari",
"version": "1.0.2", "version": "1.0.3-beta",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "timesafari", "name": "timesafari",
"version": "1.0.2", "version": "1.0.3-beta",
"dependencies": { "dependencies": {
"@capacitor-community/sqlite": "6.0.2", "@capacitor-community/sqlite": "6.0.2",
"@capacitor-mlkit/barcode-scanning": "^6.0.0", "@capacitor-mlkit/barcode-scanning": "^6.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "timesafari", "name": "timesafari",
"version": "1.0.2", "version": "1.0.3-beta",
"description": "Time Safari Application", "description": "Time Safari Application",
"author": { "author": {
"name": "Time Safari Team" "name": "Time Safari Team"
-10
View File
@@ -36,19 +36,12 @@ export default defineConfig({
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "retain-on-failure", trace: "retain-on-failure",
// Add request logging
logger: {
isEnabled: (name, severity) => severity === 'error' || name === 'api',
log: (name, severity, message, args) => console.log(`${severity}: ${message}`, args)
}
}, },
/* Configure projects for major browsers */ /* Configure projects for major browsers */
projects: [ projects: [
// { // {
// name: 'chromium-serial', // name: 'chromium-serial',
// testMatch: /.*\/(35-record-gift-from-image-share|40-add-contact)\.spec\.ts/,
// use: { // use: {
// ...devices['Desktop Chrome'], // ...devices['Desktop Chrome'],
// permissions: ["clipboard-read"], // permissions: ["clipboard-read"],
@@ -57,13 +50,11 @@ export default defineConfig({
// }, // },
// { // {
// name: 'firefox-serial', // name: 'firefox-serial',
// testMatch: /.*\/(35-record-gift-from-image-share|40-add-contact)\.spec\.ts/,
// use: { ...devices['Desktop Firefox'] }, // use: { ...devices['Desktop Firefox'] },
// workers: 1, // workers: 1,
// }, // },
{ {
name: 'chromium', name: 'chromium',
testMatch: /^(?!.*\/(35-record-gift-from-image-share|40-add-contact)\.spec\.ts).+\.spec\.ts$/,
use: { use: {
...devices['Desktop Chrome'], ...devices['Desktop Chrome'],
permissions: ["clipboard-read"], permissions: ["clipboard-read"],
@@ -71,7 +62,6 @@ export default defineConfig({
}, },
{ {
name: 'firefox', name: 'firefox',
testMatch: /^(?!.*\/(35-record-gift-from-image-share|40-add-contact)\.spec\.ts).+\.spec\.ts$/,
use: { ...devices['Desktop Firefox'] }, use: { ...devices['Desktop Firefox'] },
}, },
+1 -1
View File
@@ -102,7 +102,7 @@
icon-name="chart" icon-name="chart"
svg-class="-ml-1 mr-3 h-5 w-5" svg-class="-ml-1 mr-3 h-5 w-5"
/> />
Download Account Show Account Seed
</button> </button>
<button <button
+4 -4
View File
@@ -144,7 +144,7 @@ export default class QuickActionBvcBeginView extends Vue {
"HUR", "HUR",
BVC_MEETUPS_PROJECT_CLAIM_ID, BVC_MEETUPS_PROJECT_CLAIM_ID,
); );
if (timeResult.type === "success") { if (timeResult.success) {
timeSuccess = true; timeSuccess = true;
} else { } else {
logger.error("Error sending time:", timeResult); logger.error("Error sending time:", timeResult);
@@ -154,7 +154,7 @@ export default class QuickActionBvcBeginView extends Vue {
type: "danger", type: "danger",
title: "Error", title: "Error",
text: text:
timeResult?.error?.userMessage || timeResult?.error ||
"There was an error sending the time.", "There was an error sending the time.",
}, },
5000, 5000,
@@ -171,7 +171,7 @@ export default class QuickActionBvcBeginView extends Vue {
apiServer, apiServer,
axios, axios,
); );
if (attendResult.type === "success") { if (attendResult.success) {
attendedSuccess = true; attendedSuccess = true;
} else { } else {
logger.error("Error sending attendance:", attendResult); logger.error("Error sending attendance:", attendResult);
@@ -181,7 +181,7 @@ export default class QuickActionBvcBeginView extends Vue {
type: "danger", type: "danger",
title: "Error", title: "Error",
text: text:
attendResult?.error?.userMessage || attendResult?.error ||
"There was an error sending the attendance.", "There was an error sending the attendance.",
}, },
5000, 5000,
+1 -1
View File
@@ -110,7 +110,7 @@ test('Record something given', async ({ page }) => {
// Refresh home view and check gift // Refresh home view and check gift
await page.goto('./'); await page.goto('./');
const item = await page.locator('li').filter({ hasText: finalTitle }); const item = await page.locator('li').filter({ hasText: finalTitle });
await item.locator('[data-testid="circle-info-link"]').click(); await item.getByTestId('circle-info-link').first().click();
await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible();
await expect(page.getByText(finalTitle, { exact: true })).toBeVisible(); await expect(page.getByText(finalTitle, { exact: true })).toBeVisible();
const page1Promise = page.waitForEvent('popup'); const page1Promise = page.waitForEvent('popup');
@@ -90,7 +90,7 @@ test('Record item given from image-share', async ({ page }) => {
// Refresh home view and check gift // Refresh home view and check gift
await page.goto('./'); await page.goto('./');
const item1 = page.locator('li').filter({ hasText: finalTitle }); const item1 = page.locator('li').filter({ hasText: finalTitle }).first();
await expect(item1.getByRole('img')).toBeVisible(); await expect(item1.getByRole('img')).toBeVisible();
}); });
+7 -6
View File
@@ -102,7 +102,7 @@ test('Add contact, record gift, confirm gift', async ({ page }) => {
await expect(page.locator('li.border-b')).toContainText(userName); await expect(page.locator('li.border-b')).toContainText(userName);
// Rename contact // Rename contact
await page.locator(`li[data-testid="contactListItem"] h2:has-text("${userName}") + span svg.fa-circle-info`).click(); await page.getByTestId(`contactListItem`).locator(`h2 a:has-text("${userName}")`).click();
// now on the DID view page // now on the DID view page
await page.locator('h2 svg.fa-pen').click(); await page.locator('h2 svg.fa-pen').click();
// now on the contact edit page // now on the contact edit page
@@ -116,10 +116,11 @@ test('Add contact, record gift, confirm gift', async ({ page }) => {
// Confirm that home shows contact in "Record Something…" // Confirm that home shows contact in "Record Something…"
await page.goto('./'); await page.goto('./');
await page.getByTestId('closeOnboardingAndFinish').click(); await page.getByTestId('closeOnboardingAndFinish').click();
await expect(page.locator('#sectionRecordSomethingGiven ul li').filter({ hasText: contactName }).nth(0)).toBeVisible(); const userGaveLink = page.locator('#sectionRecordSomethingGiven ul li').filter({ hasText: contactName }).nth(0);
await expect(userGaveLink).toBeVisible();
await userGaveLink.click();
// Record something given by new contact // Record something given by new contact
await page.getByRole('heading', { name: contactName }).click();
await page.getByPlaceholder('What was given').fill(finalTitle); await page.getByPlaceholder('What was given').fill(finalTitle);
await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString()); await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString());
await page.getByRole('button', { name: 'Sign & Send' }).click(); await page.getByRole('button', { name: 'Sign & Send' }).click();
@@ -130,7 +131,7 @@ test('Add contact, record gift, confirm gift', async ({ page }) => {
// Firefox complains on load the initial feed here when we use the test server. // Firefox complains on load the initial feed here when we use the test server.
// It may be similar to the CORS problem below. // It may be similar to the CORS problem below.
await page.locator('li').filter({ hasText: finalTitle }).locator('a').click(); await page.locator('li').filter({ hasText: finalTitle }).getByTestId('circle-info-link').click();
await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible();
await expect(page.getByText(finalTitle, { exact: true })).toBeVisible(); await expect(page.getByText(finalTitle, { exact: true })).toBeVisible();
@@ -154,7 +155,7 @@ test('Add contact, record gift, confirm gift', async ({ page }) => {
// Go to home view and look for gift // Go to home view and look for gift
await page.goto('./'); await page.goto('./');
await page.getByTestId('closeOnboardingAndFinish').click(); await page.getByTestId('closeOnboardingAndFinish').click();
const giftLink = page.locator('li').filter({ hasText: finalTitle }).locator('a'); const giftLink = page.locator('li').filter({ hasText: finalTitle }).getByTestId('circle-info-link').first();
await expect(giftLink).toBeVisible(); await expect(giftLink).toBeVisible();
await giftLink.click(); await giftLink.click();
@@ -226,7 +227,7 @@ test('Add contact, copy details, delete, and import from paste & from file', asy
// See a different clipboard solution below. // See a different clipboard solution below.
// see contact details on the second contact // see contact details on the second contact
await page.getByTestId('contactListItem').nth(1).locator('a').click(); await page.getByTestId('contactListItem').nth(1).locator(`h2 a)`).click();
await page.getByRole('heading', { name: 'Identifier Details' }).isVisible(); await page.getByRole('heading', { name: 'Identifier Details' }).isVisible();
// remove contact // remove contact
await page.locator('button > svg.fa-trash-can').click(); await page.locator('button > svg.fa-trash-can').click();
+4 -4
View File
@@ -63,7 +63,7 @@ export async function deleteContact(page: Page, did: string): Promise<void> {
await page.goto('./contacts'); await page.goto('./contacts');
const contactName = createContactName(did); const contactName = createContactName(did);
// go to the detail page for this contact // go to the detail page for this contact
await page.locator(`li[data-testid="contactListItem"] h2:has-text("${contactName}") + span svg.fa-circle-info`).click(); await page.getByTestId(`contactListItem`).locator(`h2 a:has-text("${contactName}")`).click();
// delete the contact // delete the contact
await page.locator('button > svg.fa-trash-can').click(); await page.locator('button > svg.fa-trash-can').click();
await page.locator('div[role="alert"] button:has-text("Yes")').click(); await page.locator('div[role="alert"] button:has-text("Yes")').click();
@@ -82,7 +82,7 @@ export async function generateNewEthrUser(page: Page): Promise<string> {
return newDid; return newDid;
} }
// Generate a new random user and register them. // Generate a new random user, register them, and add them as a contact with name from createContactName.
// Note that this makes 000 the active user. Use switchToUser to switch to this DID. // Note that this makes 000 the active user. Use switchToUser to switch to this DID.
export async function generateAndRegisterEthrUser(page: Page): Promise<string> { export async function generateAndRegisterEthrUser(page: Page): Promise<string> {
const newDid = await generateNewEthrUser(page); const newDid = await generateNewEthrUser(page);
@@ -109,7 +109,7 @@ export async function generateRandomString(length: number): Promise<string> {
// Function to create an array of unique strings // Function to create an array of unique strings
export async function createUniqueStringsArray(count: number): Promise<string[]> { export async function createUniqueStringsArray(count: number): Promise<string[]> {
const stringsArray = []; const stringsArray: string[] = [];
const stringLength = 16; const stringLength = 16;
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
@@ -122,7 +122,7 @@ export async function createUniqueStringsArray(count: number): Promise<string[]>
// Function to create an array of two-digit non-zero numbers // Function to create an array of two-digit non-zero numbers
export async function createRandomNumbersArray(count: number): Promise<number[]> { export async function createRandomNumbersArray(count: number): Promise<number[]> {
const numbersArray = []; const numbersArray: number[] = [];
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
let randomNumber = Math.floor(Math.random() * 99) + 1; let randomNumber = Math.floor(Math.random() * 99) + 1;