diff --git a/frontend/src/app/components/masonry/masonry.component.html b/frontend/src/app/components/masonry/masonry.component.html
index 6dbc743..a6cb881 100644
--- a/frontend/src/app/components/masonry/masonry.component.html
+++ b/frontend/src/app/components/masonry/masonry.component.html
@@ -1 +1,3 @@
-
+
+
+
diff --git a/frontend/src/app/components/masonry/masonry.component.scss b/frontend/src/app/components/masonry/masonry.component.scss
index e69de29..1c3c4e9 100644
--- a/frontend/src/app/components/masonry/masonry.component.scss
+++ b/frontend/src/app/components/masonry/masonry.component.scss
@@ -0,0 +1,11 @@
+:host {
+ display: flex;
+ flex-direction: row;
+}
+
+.column {
+ display: flex;
+ flex-grow: 1;
+ flex-basis: 0;
+ flex-direction: column;
+}
diff --git a/frontend/src/app/components/masonry/masonry.component.ts b/frontend/src/app/components/masonry/masonry.component.ts
index 97d3e90..953a1c4 100644
--- a/frontend/src/app/components/masonry/masonry.component.ts
+++ b/frontend/src/app/components/masonry/masonry.component.ts
@@ -3,13 +3,15 @@ import {
Component,
ContentChildren,
ElementRef,
- OnChanges,
- OnInit,
+ Input,
+ OnDestroy,
QueryList,
- SimpleChanges,
- ViewChild,
+ ViewChildren
} from '@angular/core';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
+import { combineLatest, Subscription } from 'rxjs';
+import { RemoveChildren } from 'src/app/util/remove-children';
+import { Throttle } from 'src/app/util/throttle';
import { MasonryItemDirective } from './masonry-item.directive';
@Component({
@@ -17,9 +19,17 @@ import { MasonryItemDirective } from './masonry-item.directive';
templateUrl: './masonry.component.html',
styleUrls: ['./masonry.component.scss'],
})
-export class MasonryComponent implements AfterViewInit {
+export class MasonryComponent implements AfterViewInit, OnDestroy {
+ @Input('columns') column_count: number = 1;
+ @Input('update-speed') update_speed: number = 200;
+
@ContentChildren(MasonryItemDirective)
- content: QueryList;
+ private content: QueryList;
+
+ @ViewChildren('column')
+ private columns: QueryList>;
+
+ private sizesSubscription: Subscription | null = null;
ngAfterViewInit(): void {
this.subscribeContent();
@@ -27,8 +37,58 @@ export class MasonryComponent implements AfterViewInit {
@AutoUnsubscribe()
private subscribeContent() {
- return this.content.changes.subscribe((items) => {
- console.log('a', items.toArray());
- });
+ return this.content.changes.subscribe(
+ (items: QueryList) => {
+ const sizes = items.map((i) => i.getSize());
+
+ if (this.sizesSubscription) {
+ this.sizesSubscription.unsubscribe();
+ }
+
+ this.sizesSubscription = combineLatest(sizes)
+ .pipe(Throttle(this.update_speed))
+ .subscribe((output) => {
+ this.resortItems(items);
+ });
+
+ this.resortItems(items);
+ }
+ );
+ }
+
+ private resortItems(items: QueryList) {
+ const itemsArray = items.toArray();
+ const columnsArray = this.columns.map((c) => c.nativeElement);
+
+ for (let i = 0; i < columnsArray.length; i++) {
+ RemoveChildren(columnsArray[i]);
+ }
+
+ const columnSizes = columnsArray.map((c) => 0);
+
+ for (let i = 0; i < itemsArray.length; i++) {
+ const item = itemsArray[i];
+
+ let smallestColumn = 0;
+ let smallestColumnSize = columnSizes[0];
+ for (let j = 1; j < columnSizes.length; j++) {
+ let better_j = (j + i) % columnSizes.length;
+
+ if (columnSizes[better_j] <= smallestColumnSize) {
+ smallestColumn = better_j;
+ smallestColumnSize = columnSizes[better_j];
+ }
+ }
+
+ columnsArray[smallestColumn].appendChild(item.getElement());
+ columnSizes[smallestColumn] +=
+ item.getLastSize()?.contentRect.height ?? 0;
+ }
+ }
+
+ ngOnDestroy() {
+ if (this.sizesSubscription) {
+ this.sizesSubscription.unsubscribe();
+ }
}
}
diff --git a/frontend/src/app/routes/images/images.component.html b/frontend/src/app/routes/images/images.component.html
index 2daa283..6924587 100644
--- a/frontend/src/app/routes/images/images.component.html
+++ b/frontend/src/app/routes/images/images.component.html
@@ -1,5 +1,5 @@
-
-
+
+
Image by you
@@ -21,35 +21,6 @@
-
-
-
-
-
- Image by you
-
- Uploaded {{ image.created | amTimeAgo }}
-
-
-
-
-
-
-
-
-
-
-
-
-