diff --git a/firebase.json b/firebase.json index 00a56f63..21ed6bcc 100644 --- a/firebase.json +++ b/firebase.json @@ -1,7 +1,11 @@ { "hosting": { "public": "dist/musil", - "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], "rewrites": [ { "source": "/**/n/**", @@ -21,7 +25,8 @@ "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint", "npm --prefix \"$RESOURCE_DIR\" run build" - ] + ], + "source": "functions" }, "storage": { "rules": "storage.rules" diff --git a/firestore.rules b/firestore.rules index 00146dfe..3ca8a6a8 100644 --- a/firestore.rules +++ b/firestore.rules @@ -2,18 +2,20 @@ rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /articles/{articleId} { - allow read: if true; - allow create: if request.auth.uid != null; - allow update: if request.auth.uid == resource.data.uid && resource.data.uid == request.resource.data.uid; + allow read: if resource.data.isPublic == true || request.auth.uid == resource.data.uid; + allow create: if request.auth.uid == request.resource.data.uid; + allow update: if request.auth.uid == resource.data.uid && request.resource.data.uid == resource.data.uid; allow delete: if request.auth.uid == resource.data.uid; } match /users/{userId} { allow read: if true; - allow write: if request.auth.uid == userId; - } - match /users/{userId}/likedArticles/{articleId} { - allow read: if true; - allow write: if request.auth.uid == userId; + allow create: if request.auth.uid == request.resource.data.uid; + allow update: if request.auth.uid == resource.data.uid && request.resource.data.uid == resource.data.uid; + allow delete: if request.auth.uid == resource.data.uid; + match /likedArticles/{articleId} { + allow read: if true; + allow write: if request.auth.uid == userId; + } } } } diff --git a/functions/.gitignore b/functions/.gitignore index 9d7b336d..a1f8593d 100644 --- a/functions/.gitignore +++ b/functions/.gitignore @@ -7,3 +7,8 @@ typings/ node_modules/ lib/ +.runtimeconfig.json + +firebase-debug.log +firestore-debug.log +ui-debug.log diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 1ce41cff..d441b950 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,9 +15,16 @@ import { import { FooterComponent } from './footer/footer.component'; import { AngularFireModule } from '@angular/fire'; import { AngularFireAnalyticsModule } from '@angular/fire/analytics'; -import { AngularFirestoreModule } from '@angular/fire/firestore'; +import { + AngularFirestoreModule, + SETTINGS as FIRESTORE_SETTINGS, +} from '@angular/fire/firestore'; import { AngularFireStorageModule } from '@angular/fire/storage'; -import { AngularFireFunctionsModule, REGION } from '@angular/fire/functions'; +import { + AngularFireFunctionsModule, + REGION, + ORIGIN, +} from '@angular/fire/functions'; import { AngularFireAuthModule } from '@angular/fire/auth'; import { environment } from '../environments/environment'; import { FroalaEditorModule, FroalaViewModule } from 'angular-froala-wysiwyg'; @@ -75,6 +82,14 @@ import { MatPaginatorIntlJaModule } from './mat-paginator-intl-ja/mat-paginator- { provide: REGION, useValue: 'asia-northeast1' }, { provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 4000 } }, { provide: MatPaginatorIntl, useClass: MatPaginatorIntlJaModule }, + // { + // provide: ORIGIN, + // useValue: environment.production ? undefined : 'http://localhost:5001', + // }, + // { + // provide: FIRESTORE_SETTINGS, + // useValue: environment.production ? {} : { host: 'localhost:8080', ssl: false }, + // }, ], bootstrap: [AppComponent], }) diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 07aa898a..35a22b35 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -10,5 +10,8 @@ >お問い合わせ(TwitterDM)open_in_new - + diff --git a/src/app/footer/footer.component.scss b/src/app/footer/footer.component.scss index 8edb27f0..1a2770ab 100644 --- a/src/app/footer/footer.component.scss +++ b/src/app/footer/footer.component.scss @@ -1,3 +1,5 @@ +@import 'mixins'; + .footer { background-color: inherit; padding: 16px 0 32px; @@ -8,6 +10,9 @@ a { margin: 0 8px 8px; text-align: center; + @include sp { + font-size: 14px; + } } } } @@ -17,4 +22,7 @@ mat-icon { .copyright { text-align: center; margin: 8px 0px; + @include sp { + font-size: 14px; + } } diff --git a/src/app/mypage/liked-articles/liked-articles.component.ts b/src/app/mypage/liked-articles/liked-articles.component.ts index 8fdec2b4..c5a7776d 100644 --- a/src/app/mypage/liked-articles/liked-articles.component.ts +++ b/src/app/mypage/liked-articles/liked-articles.component.ts @@ -14,7 +14,7 @@ export class LikedArticlesComponent implements OnInit { articles$: Observable< ArticleWithAuthor[] > = this.articleService - .getMyLikedArticles(this.userService.mypageUser.uid) + .getMyLikedArticles(this.userService.mypageUser?.uid) .pipe( take(1), tap(() => { diff --git a/src/app/mypage/my-articles/my-articles.component.ts b/src/app/mypage/my-articles/my-articles.component.ts index 99a150ef..665a25fd 100644 --- a/src/app/mypage/my-articles/my-articles.component.ts +++ b/src/app/mypage/my-articles/my-articles.component.ts @@ -14,7 +14,7 @@ export class MyArticlesComponent implements OnInit { articles$: Observable< ArticleWithAuthor[] > = this.articleService - .getMyArticlesPublic(this.userService.mypageUser.uid) + .getMyArticlesPublic(this.userService.mypageUser?.uid) .pipe( take(1), tap(() => { diff --git a/src/app/mypage/mypage.module.ts b/src/app/mypage/mypage.module.ts index a2f3960e..8e57381b 100644 --- a/src/app/mypage/mypage.module.ts +++ b/src/app/mypage/mypage.module.ts @@ -15,6 +15,7 @@ import { ClipboardModule } from '@angular/cdk/clipboard'; import { MyArticlesComponent } from './my-articles/my-articles.component'; import { LikedArticlesComponent } from './liked-articles/liked-articles.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { StringToLinkPipe } from '../pipes/string-to-link.pipe'; @NgModule({ declarations: [ @@ -22,6 +23,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; NoteComponent, MyArticlesComponent, LikedArticlesComponent, + StringToLinkPipe, ], imports: [ CommonModule, diff --git a/src/app/mypage/mypage/mypage.component.html b/src/app/mypage/mypage/mypage.component.html index f30dde97..8c0bb96e 100644 --- a/src/app/mypage/mypage/mypage.component.html +++ b/src/app/mypage/mypage/mypage.component.html @@ -22,7 +22,7 @@

{{ user.userName }}

@{{ user.screenName }}

{{ user.userName }} class="mypage__twitter" target="_blank" rel="noopener noreferrer" + *ngIf="user.uid !== authService.uid" > Twitterロゴ { + if (event instanceof NavigationStart) { + this.scrollService.saveScrollPosition('mypage'); + } + if (event instanceof NavigationEnd) { + this.scrollService.restoreScrollPosition('mypage'); + } + }); } - - stringToLink(description: string): string { - const linkReg = new RegExp( - /(http(s)?:\/\/[a-zA-Z0-9-.!'()*;/?:@&=+$,%#]+)/gi - ); - const toATag = - "$1"; - const link = description.replace(linkReg, toATag); - return link; - } - ngOnInit(): void {} } diff --git a/src/app/mypage/note/note.component.html b/src/app/mypage/note/note.component.html index 063ab840..0f004abc 100644 --- a/src/app/mypage/note/note.component.html +++ b/src/app/mypage/note/note.component.html @@ -178,7 +178,7 @@

{{ article.title }}

> {{ article.title }} class="note-footer__twitter" target="_blank" rel="noopener noreferrer" + *ngIf="article.author.uid !== authService.uid" > $1"; - const link = description.replace(linkReg, toATag); - return link; - } else { - return description; - } - } - clickedLike(articleId: string) { if (this.authService.uid && !this.isLiked) { this.likeService.likeArticle(articleId, this.authService.uid); diff --git a/src/app/notes/create/create.component.html b/src/app/notes/create/create.component.html index 49c4cd6f..48cc3b83 100644 --- a/src/app/notes/create/create.component.html +++ b/src/app/notes/create/create.component.html @@ -1,7 +1,7 @@
- +
- 公開 - + +
diff --git a/src/app/search-input/search-input.component.scss b/src/app/search-input/search-input.component.scss index 0a4bbe9e..22074978 100644 --- a/src/app/search-input/search-input.component.scss +++ b/src/app/search-input/search-input.component.scss @@ -45,15 +45,22 @@ } } -.smart-search { +.sp-search { display: none; @include sp { display: block; } } +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: none; +} + .active { - @include sp { - display: block; - } + display: block; } diff --git a/src/app/services/article.service.ts b/src/app/services/article.service.ts index acf1dea0..cca5b7be 100644 --- a/src/app/services/article.service.ts +++ b/src/app/services/article.service.ts @@ -80,6 +80,7 @@ export class ArticleService { .where('uid', '==', uid) .where('isPublic', '==', true) .orderBy('updatedAt', 'desc') + .limit(20) ) .valueChanges() .pipe( @@ -102,7 +103,7 @@ export class ArticleService { getMyLikedArticles(uid: string): Observable { const sorted = this.db .collection(`users/${uid}/likedArticles`, (ref) => - ref.orderBy('updatedAt', 'desc') + ref.orderBy('updatedAt', 'desc').limit(20) ) .valueChanges() .pipe( @@ -126,7 +127,7 @@ export class ArticleService { getMyArticlesAll(uid: string): Observable { return this.db .collection
(`articles`, (ref) => - ref.where('uid', '==', uid).orderBy('updatedAt', 'desc') + ref.where('uid', '==', uid).orderBy('updatedAt', 'desc').limit(20) ) .valueChanges(); } diff --git a/src/app/services/scroll.service.ts b/src/app/services/scroll.service.ts index 2f0736fb..38d239ab 100644 --- a/src/app/services/scroll.service.ts +++ b/src/app/services/scroll.service.ts @@ -5,6 +5,7 @@ import { Injectable } from '@angular/core'; }) export class ScrollService { scrollPosYs: { [key: string]: number } = {}; + maxAttemptCount = 5; constructor() {} @@ -15,10 +16,15 @@ export class ScrollService { } restoreScrollPosition(id: string): void { - if (id) { + for ( + let attemptCount = 0; + attemptCount < this.maxAttemptCount; + attemptCount++ + ) { + const position = this.scrollPosYs[id] ? this.scrollPosYs[id] : 0; setTimeout(() => { - window.scrollTo(0, this.scrollPosYs[id]); - }, 100); + window.scroll(0, position); + }, 30); } } } diff --git a/src/app/settings/settings/settings.component.html b/src/app/settings/settings/settings.component.html index 2c9d52f3..1449625e 100644 --- a/src/app/settings/settings/settings.component.html +++ b/src/app/settings/settings/settings.component.html @@ -2,27 +2,31 @@

アカウント設定

プロフィール

+ +
- - - - ユーザー名* + ユーザー名 プロフィール #userNameInput placeholder="ユーザー名*" autocomplete="off" + required /> {{ userNameInput.value?.length || 0 }}/{{ @@ -44,12 +49,16 @@

プロフィール

>
- スクリーンネーム(Twitterアカウントに紐付いています) +
+ スクリーンネーム(Twitterアカウントから更新) +
@{{ user.screenName }}
- + 自己紹介