Skip to content

Commit

Permalink
Rework of main page layout:
Browse files Browse the repository at this point in the history
- player moved to page bottom
- list can now be scrolled (fully) while playing
- list vertical scrollbar now appears only when scrolling
- cleaned up list style
- improved items multiselection
  • Loading branch information
nicorac committed Dec 6, 2024
1 parent 4079033 commit 5549317
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 411 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Version history

## Version 1.10.0 (2024-12-06)

New features:

- Rework of main page layout:
- player moved to page bottom
- list can now be scrolled (fully) while playing
- list vertical scrollbar now appears only when scrolling
- cleaned up list style
- improved items multiselection

Bug fixes:

- scrolling list causes player to stop when playing item goes out of scope

## Version 1.9.2 (2024-11-25)

Bug fixes:
Expand Down
380 changes: 197 additions & 183 deletions package-lock.json

Large diffs are not rendered by default.

88 changes: 44 additions & 44 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,53 +21,53 @@
},
"private": true,
"dependencies": {
"@angular/cdk": "^18.2.11",
"@angular/common": "^18.2.10",
"@angular/core": "^18.2.10",
"@angular/forms": "^18.2.10",
"@angular/platform-browser": "^18.2.10",
"@angular/platform-browser-dynamic": "^18.2.10",
"@angular/router": "^18.2.10",
"@angular/cdk": "18.2.11",
"@angular/common": "18.2.11",
"@angular/core": "18.2.11",
"@angular/forms": "18.2.11",
"@angular/platform-browser": "18.2.11",
"@angular/platform-browser-dynamic": "18.2.11",
"@angular/router": "18.2.11",
"@capacitor-community/contacts": "6.1.1",
"@capacitor/android": "^6.1.2",
"@capacitor/app": "^6.0.1",
"@capacitor/clipboard": "^6.0.1",
"@capacitor/core": "^6.1.2",
"@capacitor/device": "^6.0.1",
"@capacitor/filesystem": "^6.0.1",
"@capacitor/preferences": "^6.0.2",
"@capacitor/share": "^6.0.2",
"@capacitor/status-bar": "^6.0.1",
"@capgo/capacitor-navigation-bar": "^6.1.62",
"@ionic/angular": "^8.3.4",
"capacitor-native-settings": "^6.0.1",
"filesize": "^10.1.6",
"ionicons": "^7.4.0",
"rxjs": "^7.8.1",
"tslib": "^2.7.0",
"zone.js": "^0.14.10"
"@capacitor/android": "6.1.2",
"@capacitor/app": "6.0.1",
"@capacitor/clipboard": "6.0.1",
"@capacitor/core": "6.1.2",
"@capacitor/device": "6.0.1",
"@capacitor/filesystem": "6.0.1",
"@capacitor/preferences": "6.0.2",
"@capacitor/share": "6.0.2",
"@capacitor/status-bar": "6.0.1",
"@capgo/capacitor-navigation-bar": "6.1.64",
"@ionic/angular": "8.3.4",
"capacitor-native-settings": "6.0.1",
"filesize": "10.1.6",
"ionicons": "7.4.0",
"rxjs": "7.8.1",
"tslib": "2.8.1",
"zone.js": "0.14.10"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.2.11",
"@angular-eslint/builder": "^18.4.0",
"@angular-eslint/eslint-plugin": "^18.4.0",
"@angular-eslint/eslint-plugin-template": "^18.4.0",
"@angular-eslint/template-parser": "^18.4.0",
"@angular/cli": "^18.2.11",
"@angular/compiler": "^18.2.10",
"@angular/compiler-cli": "^18.2.10",
"@capacitor/assets": "^3.0.5",
"@capacitor/cli": "^6.1.2",
"@ionic/angular-toolkit": "^12.1.1",
"@types/jasmine": "^5.1.4",
"@types/node": "^22.7.5",
"@typescript-eslint/eslint-plugin": "^8.9.0",
"@typescript-eslint/parser": "^8.9.0",
"eslint": "^9.12.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.4.3",
"ts-node": "^10.9.2",
"typescript": "^5.5.4"
"@angular-devkit/build-angular": "18.2.11",
"@angular-eslint/builder": "18.4.0",
"@angular-eslint/eslint-plugin": "18.4.0",
"@angular-eslint/eslint-plugin-template": "18.4.0",
"@angular-eslint/template-parser": "18.4.0",
"@angular/cli": "18.2.11",
"@angular/compiler": "18.2.11",
"@angular/compiler-cli": "18.2.11",
"@capacitor/assets": "3.0.5",
"@capacitor/cli": "6.1.2",
"@ionic/angular-toolkit": "12.1.1",
"@types/jasmine": "5.1.4",
"@types/node": "22.9.0",
"@typescript-eslint/eslint-plugin": "8.14.0",
"@typescript-eslint/parser": "8.14.0",
"eslint": "9.14.0",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-jsdoc": "50.4.3",
"ts-node": "10.9.2",
"typescript": "5.5.4"
},
"engines": {
"npm": ">= 10.9.0",
Expand Down
17 changes: 14 additions & 3 deletions src/app.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
body {
// default mode
--ion-color-primary: #43a047; // main color (buttons, ...)
--ion-color-primary-darker: #529055;
--ion-text-color: #000000; // text color
--ion-text-color-rgb: 0,0,0; // text color (RGB form)
// pages
Expand All @@ -10,15 +11,17 @@ body {
--ion-toolbar-color-rgb: 255,255,255;
--ion-toolbar-background: var(--ion-color-primary); // NOTE: this value must also be set in TOOLBAR_BACKGROUND_* const (app.component.ts)
// items
--ion-item-background: #ffffff;
--ion-item-color: var(--ion-text-color);
--ion-item-background: #ffffff;
--ion-item-background-selected: #f4fff0;
--item-border-color: var(--ion-color-step-300);
--item-border-color-selected: var(--ion-color-step-400);
--item-border-color-selected: var(--ion-color-primary);
--item-shadow-color-selected: var(--ion-color-step-300);
// player
--player-background-color: #b3daa3;

// dark mode (overrides)
&.dark {
--ion-color-primary: #43a047;
--ion-text-color: rgb(223, 223, 223);
--ion-text-color-rgb: 223, 223, 223; // used by menu icons
// pages
Expand All @@ -29,6 +32,9 @@ body {
--ion-toolbar-background: var(--ion-color-step-100); // NOTE: this value must also be set in TOOLBAR_BACKGROUND_* const (app.component.ts)
// items
--ion-item-background: var(--ion-color-step-100);
--ion-item-background-selected: var(--ion-color-step-150);
// player
--player-background-color: var(--ion-color-step-150);
}

// list items (settings...)
Expand Down Expand Up @@ -57,6 +63,11 @@ ion-item-divider,
--color: var(--ion-text-color);
}

.left-container {
display: flex;
justify-content: flex-start;
}

.left-right-container {
display: flex;
justify-content: space-between;
Expand Down
59 changes: 34 additions & 25 deletions src/app/components/audio-player/audio-player.component.html
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
<div class="progress">
<ion-range
label="{{ progress() | toHms }}"
labelPlacement="end"
<div class="progress-label">{{ progress() | toHms }}</div>
<ion-range class="range-bar"
[disabled]="!ready()"
[value]="progress()"
[max]="duration()"
(ionKnobMoveEnd)="onIonKnobMoveEnd($event)"
/>
<div class="progress-label">{{ duration() | toHms }}</div>
</div>

<div class="controls">
<ion-icon
class="buttons"
color="primary"
[class.disabled]="!ready()"
name="play-back"
(click)="onSeek(-1)"
/>
<ion-icon
class="buttons"
color="primary"
[class.disabled]="!ready()"
[name]="status() !== PlayerStatusEnum.Playing ? 'play' : 'pause'"
(click)="toggle()"
/>
<ion-icon
class="buttons"
color="primary"
[class.disabled]="!ready()"
name="play-forward"
(click)="onSeek(+1)"
/>
<div class="controls" [class.disabled]="!ready()">

<div class="button" (click)="onSeek(-1)">
<div class="button-in">
<ion-icon
class="icon"
color="primary"
name="play-back"
/>
</div>
</div>

<div class="button play" (click)="toggle()">
<div class="button-in">
<ion-icon
class="icon"
[name]="status() !== PlayerStatusEnum.Playing ? 'play' : 'pause'"
/>
</div>
</div>

<div class="button" (click)="onSeek(+1)">
<div class="button-in">
<ion-icon
class="icon"
color="primary"
name="play-forward"
/>
</div>
</div>

</div>
111 changes: 104 additions & 7 deletions src/app/components/audio-player/audio-player.component.scss
Original file line number Diff line number Diff line change
@@ -1,23 +1,120 @@
$buttonSize: 2.5em;

:host {
display: flex;
flex-direction: column;
align-items: center;
border-top-left-radius: 18px;
border-top-right-radius: 18px;
gap: 0;
padding: .6em 1em;
user-select: none;
box-shadow: 0 -2px 4px -1px rgba(0, 0, 0, 0.2),
0 -4px 5px 0 rgba(0, 0, 0, 0.14),
0 -1px 10px 0 rgba(0, 0, 0, 0.12);
--button-shadow-color: rgba(0,0,0,0.2);
}

:host-context(.dark) :host {
--button-shadow-color: rgba(255,255,255,0.1);
}

.controls {
display: flex;
gap: 2em;
align-items: center;
gap: 1.5em;
}

.buttons {
font-size: 2em;
line-height: 0;
.button,
.button-in {
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}

.button {
background: var(--player-background-color);
box-shadow: 0px 0px 6px 3px var(--button-shadow-color);
position: relative;
cursor: pointer;
width: $buttonSize;
height: $buttonSize;

.button-in {
width: 100%;
height: 100%;

.icon {
height: 65%;
width: 65%;
}

&:active {
width: 100%;
height: 100%;
border: 1px solid var(--ion-color-primary-darker);
box-shadow: inset 0px 0px 5px 0px var(--ion-color-step-700);

.icon {
height: 55%;
width: 55%;
}
}

}

// increase size of play button
&.play {
width: calc($buttonSize * 1.3);
height: calc($buttonSize * 1.3);
border: 3px solid var(--ion-color-primary-darker);
color: var(--ion-background-color);

.button-in {
background-color: var(--ion-color-primary);

&:active {
border: none;
box-shadow: inset -3px -3px 5px 0.1px var(--ion-color-step-700), inset 3px 3px 5px 0.7px var(--ion-color-step-800);
}
}
}

// decrease size of action buttons
&.actions {
width: calc($buttonSize * .7);
height: calc($buttonSize * .7);
}

}

.progress {
display: flex;
gap: .5em;
display: grid;
grid-template-columns: min-content minmax(0, 1fr) min-content;
align-items: center;
gap: 1em;
width: 100%;
}

.progress-label {
color: var(--ion-color-step-600)
}

.range-bar {
--bar-height: 5px;
--knob-size: 24px;
}

ion-range::part(bar) {
background: var(--ion-background-color);
box-shadow: color-mix(in srgb, var(--ion-color-primary-darker), transparent 80%) 0px 0px 0px 1px;
}

ion-range::part(bar-active) {
background: var(--ion-color-primary);
}


ion-range::part(knob) {
background: var(--ion-color-primary-darker);
}
4 changes: 1 addition & 3 deletions src/app/components/audio-player/audio-player.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Subscription } from 'rxjs';
import { IonicBundleModule } from 'src/app/IonicBundle.module';
import { Recording } from 'src/app/models/recording';
import { DatetimePipe } from 'src/app/pipes/datetime.pipe';
import { ToHmsPipe } from 'src/app/pipes/to-hms.pipe';
import { MessageBoxService } from 'src/app/services/message-box.service';
import { RecordingsService } from 'src/app/services/recordings.service';
Expand All @@ -20,8 +19,7 @@ export enum PlayerStatusEnum {
templateUrl: './audio-player.component.html',
styleUrls: ['./audio-player.component.scss'],
standalone: true,
imports: [ DatetimePipe, IonicBundleModule, ToHmsPipe ],
providers: [ DatetimePipe ],
imports: [ IonicBundleModule, ToHmsPipe ],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AudioPlayerComponent implements OnInit, OnDestroy {
Expand Down
Loading

0 comments on commit 5549317

Please sign in to comment.