1
0
Fork 0

Allow accounts to skip account setup modal

This commit is contained in:
Chocobozzz 2021-08-27 10:15:55 +02:00
parent 1ff15061b3
commit 8f58172565
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
23 changed files with 241 additions and 155 deletions

View File

@ -61,8 +61,8 @@
</p-toast> </p-toast>
<ng-container *ngIf="isUserLoggedIn()"> <ng-container *ngIf="isUserLoggedIn()">
<my-account-setup-modal #accountSetupModal></my-account-setup-modal> <my-account-setup-warning-modal #accountSetupWarningModal></my-account-setup-warning-modal>
<my-welcome-modal #welcomeModal></my-welcome-modal> <my-admin-welcome-modal #adminWelcomeModal></my-admin-welcome-modal>
<my-instance-config-warning-modal #instanceConfigWarningModal></my-instance-config-warning-modal> <my-instance-config-warning-modal #instanceConfigWarningModal></my-instance-config-warning-modal>
</ng-container> </ng-container>

View File

@ -1,5 +1,6 @@
import { Hotkey, HotkeysService } from 'angular2-hotkeys' import { Hotkey, HotkeysService } from 'angular2-hotkeys'
import { filter, map, switchMap } from 'rxjs/operators' import { forkJoin } from 'rxjs'
import { filter, first, map } from 'rxjs/operators'
import { DOCUMENT, getLocaleDirection, PlatformLocation } from '@angular/common' import { DOCUMENT, getLocaleDirection, PlatformLocation } from '@angular/common'
import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core' import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core'
import { DomSanitizer, SafeHtml } from '@angular/platform-browser' import { DomSanitizer, SafeHtml } from '@angular/platform-browser'
@ -17,15 +18,15 @@ import {
} from '@app/core' } from '@app/core'
import { HooksService } from '@app/core/plugins/hooks.service' import { HooksService } from '@app/core/plugins/hooks.service'
import { PluginService } from '@app/core/plugins/plugin.service' import { PluginService } from '@app/core/plugins/plugin.service'
import { AccountSetupWarningModalComponent } from '@app/modal/account-setup-warning-modal.component'
import { CustomModalComponent } from '@app/modal/custom-modal.component' import { CustomModalComponent } from '@app/modal/custom-modal.component'
import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component'
import { WelcomeModalComponent } from '@app/modal/welcome-modal.component' import { AdminWelcomeModalComponent } from '@app/modal/admin-welcome-modal.component'
import { AccountSetupModalComponent } from '@app/modal/account-setup-modal.component'
import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { LoadingBarService } from '@ngx-loading-bar/core' import { LoadingBarService } from '@ngx-loading-bar/core'
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
import { getShortLocale } from '@shared/core-utils/i18n' import { getShortLocale } from '@shared/core-utils/i18n'
import { BroadcastMessageLevel, HTMLServerConfig, ServerConfig, UserRole } from '@shared/models' import { BroadcastMessageLevel, HTMLServerConfig, UserRole } from '@shared/models'
import { MenuService } from './core/menu/menu.service' import { MenuService } from './core/menu/menu.service'
import { POP_STATE_MODAL_DISMISS } from './helpers' import { POP_STATE_MODAL_DISMISS } from './helpers'
import { InstanceService } from './shared/shared-instance' import { InstanceService } from './shared/shared-instance'
@ -38,8 +39,8 @@ import { InstanceService } from './shared/shared-instance'
export class AppComponent implements OnInit, AfterViewInit { export class AppComponent implements OnInit, AfterViewInit {
private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed' private static BROADCAST_MESSAGE_KEY = 'app-broadcast-message-dismissed'
@ViewChild('accountSetupModal') accountSetupModal: AccountSetupModalComponent @ViewChild('accountSetupWarningModal') accountSetupWarningModal: AccountSetupWarningModalComponent
@ViewChild('welcomeModal') welcomeModal: WelcomeModalComponent @ViewChild('adminWelcomeModal') adminWelcomeModal: AdminWelcomeModalComponent
@ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent @ViewChild('instanceConfigWarningModal') instanceConfigWarningModal: InstanceConfigWarningModalComponent
@ViewChild('customModal') customModal: CustomModalComponent @ViewChild('customModal') customModal: CustomModalComponent
@ -221,33 +222,41 @@ export class AppComponent implements OnInit, AfterViewInit {
} }
private openModalsIfNeeded () { private openModalsIfNeeded () {
this.authService.userInformationLoaded const userSub = this.authService.userInformationLoaded
.pipe( .pipe(map(() => this.authService.getUser()))
map(() => this.authService.getUser()),
filter(user => user.role === UserRole.ADMINISTRATOR), // Admin modal
switchMap(user => { userSub.pipe(
return this.serverService.getConfig() filter(user => user.role === UserRole.ADMINISTRATOR)
.pipe(map(serverConfig => ({ serverConfig, user }))) ).subscribe(user => this.openAdminModalsIfNeeded(user))
})
).subscribe(({ serverConfig, user }) => this._openAdminModalsIfNeeded(serverConfig, user)) // Account modal
userSub.pipe(
filter(user => user.role !== UserRole.ADMINISTRATOR)
).subscribe(user => this.openAccountModalsIfNeeded(user))
} }
private _openAdminModalsIfNeeded (serverConfig: ServerConfig, user: User) { private openAdminModalsIfNeeded (user: User) {
if (user.noWelcomeModal !== true) return this.welcomeModal.show() if (this.adminWelcomeModal.shouldOpen(user)) {
return this.adminWelcomeModal.show()
}
if (user.noInstanceConfigWarningModal === true || !serverConfig.signup.allowed) return if (!this.instanceConfigWarningModal.shouldOpenByUser(user)) return
this.instanceService.getAbout() forkJoin([
.subscribe(about => { this.serverService.getConfig().pipe(first()),
if ( this.instanceService.getAbout().pipe(first())
this.serverConfig.instance.name.toLowerCase() === 'peertube' || ]).subscribe(([ config, about ]) => {
!about.instance.terms || if (this.instanceConfigWarningModal.shouldOpen(config, about)) {
!about.instance.administrator || this.instanceConfigWarningModal.show(about)
!about.instance.maintenanceLifetime }
) { })
this.instanceConfigWarningModal.show(about) }
}
}) private openAccountModalsIfNeeded (user: User) {
if (this.accountSetupWarningModal.shouldOpen(user)) {
this.accountSetupWarningModal.show(user)
}
} }
private initHotkeys () { private initHotkeys () {

View File

@ -17,8 +17,8 @@ import { ConfirmComponent } from './modal/confirm.component'
import { CustomModalComponent } from './modal/custom-modal.component' import { CustomModalComponent } from './modal/custom-modal.component'
import { InstanceConfigWarningModalComponent } from './modal/instance-config-warning-modal.component' import { InstanceConfigWarningModalComponent } from './modal/instance-config-warning-modal.component'
import { QuickSettingsModalComponent } from './modal/quick-settings-modal.component' import { QuickSettingsModalComponent } from './modal/quick-settings-modal.component'
import { WelcomeModalComponent } from './modal/welcome-modal.component' import { AdminWelcomeModalComponent } from './modal/admin-welcome-modal.component'
import { AccountSetupModalComponent } from './modal/account-setup-modal.component' import { AccountSetupWarningModalComponent } from './modal/account-setup-warning-modal.component'
import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module' import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module'
import { SharedFormModule } from './shared/shared-forms' import { SharedFormModule } from './shared/shared-forms'
import { SharedGlobalIconModule } from './shared/shared-icons' import { SharedGlobalIconModule } from './shared/shared-icons'
@ -54,9 +54,9 @@ export function loadConfigFactory (server: ServerService, pluginService: PluginS
SuggestionComponent, SuggestionComponent,
HighlightPipe, HighlightPipe,
AccountSetupModalComponent, AccountSetupWarningModalComponent,
CustomModalComponent, CustomModalComponent,
WelcomeModalComponent, AdminWelcomeModalComponent,
InstanceConfigWarningModalComponent, InstanceConfigWarningModalComponent,
ConfirmComponent ConfirmComponent
], ],

View File

@ -55,6 +55,7 @@ export class User implements UserServerModel {
noInstanceConfigWarningModal: boolean noInstanceConfigWarningModal: boolean
noWelcomeModal: boolean noWelcomeModal: boolean
noAccountSetupWarningModal: boolean
pluginAuth: string | null pluginAuth: string | null
@ -98,6 +99,7 @@ export class User implements UserServerModel {
this.noInstanceConfigWarningModal = hash.noInstanceConfigWarningModal this.noInstanceConfigWarningModal = hash.noInstanceConfigWarningModal
this.noWelcomeModal = hash.noWelcomeModal this.noWelcomeModal = hash.noWelcomeModal
this.noAccountSetupWarningModal = hash.noAccountSetupWarningModal
this.notificationSettings = hash.notificationSettings this.notificationSettings = hash.notificationSettings

View File

@ -1,73 +0,0 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { AuthService, ServerService, User, UserService } from '@app/core'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
import { HTMLServerConfig } from '@shared/models'
@Component({
selector: 'my-account-setup-modal',
templateUrl: './account-setup-modal.component.html',
styleUrls: [ './account-setup-modal.component.scss' ]
})
export class AccountSetupModalComponent implements OnInit {
@ViewChild('modal', { static: true }) modal: ElementRef
user: User = null
ref: NgbModalRef = null
private serverConfig: HTMLServerConfig
constructor (
private userService: UserService,
private authService: AuthService,
private modalService: NgbModal,
private serverService: ServerService
) { }
get userInformationLoaded () {
return this.authService.userInformationLoaded
}
get instanceName () {
return this.serverConfig.instance.name
}
get isUserRoot () {
return this.user.username === 'root'
}
get hasAccountAvatar () {
return !!this.user.account.avatar
}
get hasAccountDescription () {
return !!this.user.account.description
}
ngOnInit () {
this.serverConfig = this.serverService.getHTMLConfig()
this.authService.userInformationLoaded
.subscribe(
() => {
this.user = this.authService.getUser()
if (this.isUserRoot) return
if (this.hasAccountAvatar && this.hasAccountDescription) return
if (this.userService.hasSignupInThisSession()) return
this.show()
}
)
}
show () {
if (this.ref) return
this.ref = this.modalService.open(this.modal, {
centered: true,
backdrop: 'static',
keyboard: false,
size: 'md'
})
}
}

View File

@ -12,12 +12,18 @@
<p i18n>Help moderators and other users to know <strong>who you are</strong> by:</p> <p i18n>Help moderators and other users to know <strong>who you are</strong> by:</p>
<ul> <ul>
<li *ngIf="!hasAccountAvatar" i18n>Uploading an <strong>avatar</strong></li> <li *ngIf="!hasAccountAvatar(user)" i18n>Uploading an <strong>avatar</strong></li>
<li *ngIf="!hasAccountDescription" i18n>Writing a <strong>description</strong></li> <li *ngIf="!hasAccountDescription(user)" i18n>Writing a <strong>description</strong></li>
</ul> </ul>
</div> </div>
<div class="modal-footer inputs"> <div class="modal-footer inputs">
<my-peertube-checkbox
inputName="stopDisplayModal" [(ngModel)]="stopDisplayModal"
i18n-labelText labelText="Don't show me this anymore"
>
</my-peertube-checkbox>
<input <input
type="button" role="button" i18n-value value="Remind me later" class="peertube-button grey-button" type="button" role="button" i18n-value value="Remind me later" class="peertube-button grey-button"
(click)="hide()" (key.enter)="hide()" (click)="hide()" (key.enter)="hide()"

View File

@ -0,0 +1,79 @@
import { Component, ElementRef, ViewChild } from '@angular/core'
import { Notifier, ServerService, User, UserService } from '@app/core'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
@Component({
selector: 'my-account-setup-warning-modal',
templateUrl: './account-setup-warning-modal.component.html',
styleUrls: [ './account-setup-warning-modal.component.scss' ]
})
export class AccountSetupWarningModalComponent {
@ViewChild('modal', { static: true }) modal: ElementRef
stopDisplayModal = false
ref: NgbModalRef
user: User
private LOCAL_STORAGE_KEYS = {
NO_ACCOUNT_SETUP_WARNING_MODAL: 'no_account_setup_warning_modal'
}
constructor (
private userService: UserService,
private modalService: NgbModal,
private notifier: Notifier,
private serverService: ServerService
) { }
get instanceName () {
return this.serverService.getHTMLConfig().instance.name
}
hasAccountAvatar (user: User) {
return !!user.account.avatar
}
hasAccountDescription (user: User) {
return !!user.account.description
}
shouldOpen (user: User) {
if (user.noAccountSetupWarningModal === true) return false
if (peertubeLocalStorage.getItem(this.LOCAL_STORAGE_KEYS.NO_ACCOUNT_SETUP_WARNING_MODAL) === 'true') return false
if (this.hasAccountAvatar(user) && this.hasAccountDescription(user)) return false
if (this.userService.hasSignupInThisSession()) return false
return true
}
show (user: User) {
this.user = user
if (this.ref) return
this.ref = this.modalService.open(this.modal, {
centered: true,
backdrop: 'static',
keyboard: false,
size: 'md'
})
this.ref.result.finally(() => {
if (this.stopDisplayModal === true) this.doNotOpenAgain()
})
}
private doNotOpenAgain () {
peertubeLocalStorage.setItem(this.LOCAL_STORAGE_KEYS.NO_ACCOUNT_SETUP_WARNING_MODAL, 'true')
this.userService.updateMyProfile({ noAccountSetupWarningModal: true })
.subscribe({
next: () => console.log('We will not open the account setup modal again.'),
error: err => this.notifier.error(err.message)
})
}
}

View File

@ -1,14 +1,14 @@
import { Component, ElementRef, ViewChild } from '@angular/core' import { Component, ElementRef, ViewChild } from '@angular/core'
import { Notifier, UserService } from '@app/core' import { Notifier, User, UserService } from '@app/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
@Component({ @Component({
selector: 'my-welcome-modal', selector: 'my-admin-welcome-modal',
templateUrl: './welcome-modal.component.html', templateUrl: './admin-welcome-modal.component.html',
styleUrls: [ './welcome-modal.component.scss' ] styleUrls: [ './admin-welcome-modal.component.scss' ]
}) })
export class WelcomeModalComponent { export class AdminWelcomeModalComponent {
@ViewChild('modal', { static: true }) modal: ElementRef @ViewChild('modal', { static: true }) modal: ElementRef
private LOCAL_STORAGE_KEYS = { private LOCAL_STORAGE_KEYS = {
@ -21,10 +21,14 @@ export class WelcomeModalComponent {
private notifier: Notifier private notifier: Notifier
) { } ) { }
show () { shouldOpen (user: User) {
const result = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_KEYS.NO_WELCOME_MODAL) if (user.noWelcomeModal === true) return false
if (result === 'true') return if (peertubeLocalStorage.getItem(this.LOCAL_STORAGE_KEYS.NO_WELCOME_MODAL) === 'true') return false
return true
}
show () {
this.modalService.open(this.modal, { this.modalService.open(this.modal, {
centered: true, centered: true,
backdrop: 'static', backdrop: 'static',

View File

@ -1,9 +1,9 @@
import { Location } from '@angular/common' import { Location } from '@angular/common'
import { Component, ElementRef, ViewChild } from '@angular/core' import { Component, ElementRef, ViewChild } from '@angular/core'
import { Notifier, UserService } from '@app/core' import { Notifier, User, UserService } from '@app/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
import { About } from '@shared/models/server' import { About, ServerConfig } from '@shared/models/server'
@Component({ @Component({
selector: 'my-instance-config-warning-modal', selector: 'my-instance-config-warning-modal',
@ -27,10 +27,23 @@ export class InstanceConfigWarningModalComponent {
private notifier: Notifier private notifier: Notifier
) { } ) { }
show (about: About) { shouldOpenByUser (user: User) {
const result = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_KEYS.NO_INSTANCE_CONFIG_WARNING_MODAL) if (user.noInstanceConfigWarningModal === true) return false
if (result === 'true') return if (peertubeLocalStorage.getItem(this.LOCAL_STORAGE_KEYS.NO_INSTANCE_CONFIG_WARNING_MODAL) === 'true') return false
return true
}
shouldOpen (serverConfig: ServerConfig, about: About) {
if (!serverConfig.signup.allowed) return false
return serverConfig.instance.name.toLowerCase() === 'peertube' ||
!about.instance.terms ||
!about.instance.administrator ||
!about.instance.maintenanceLifetime
}
show (about: About) {
if (this.location.path().startsWith('/admin/config/edit-custom')) return if (this.location.path().startsWith('/admin/config/edit-custom')) return
this.about = about this.about = about

View File

@ -203,6 +203,7 @@ async function updateMe (req: express.Request, res: express.Response) {
'videoLanguages', 'videoLanguages',
'theme', 'theme',
'noInstanceConfigWarningModal', 'noInstanceConfigWarningModal',
'noAccountSetupWarningModal',
'noWelcomeModal' 'noWelcomeModal'
] ]

View File

@ -81,11 +81,7 @@ function isUserAutoPlayNextVideoPlaylistValid (value: any) {
return isBooleanValid(value) return isBooleanValid(value)
} }
function isNoInstanceConfigWarningModal (value: any) { function isUserNoModal (value: any) {
return isBooleanValid(value)
}
function isNoWelcomeModal (value: any) {
return isBooleanValid(value) return isBooleanValid(value)
} }
@ -119,6 +115,5 @@ export {
isUserAutoPlayNextVideoPlaylistValid, isUserAutoPlayNextVideoPlaylistValid,
isUserDisplayNameValid, isUserDisplayNameValid,
isUserDescriptionValid, isUserDescriptionValid,
isNoInstanceConfigWarningModal, isUserNoModal
isNoWelcomeModal
} }

View File

@ -24,7 +24,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const LAST_MIGRATION_VERSION = 660 const LAST_MIGRATION_VERSION = 665
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -0,0 +1,27 @@
import * as Sequelize from 'sequelize'
async function up (utils: {
transaction: Sequelize.Transaction
queryInterface: Sequelize.QueryInterface
sequelize: Sequelize.Sequelize
db: any
}): Promise<void> {
{
const data = {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
}
await utils.queryInterface.addColumn('user', 'noAccountSetupWarningModal', data)
}
}
function down (options) {
throw new Error('Not implemented.')
}
export {
up,
down
}

View File

@ -9,14 +9,13 @@ import { UserRegister } from '../../../shared/models/users/user-register.model'
import { toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' import { toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
import { isThemeNameValid } from '../../helpers/custom-validators/plugins' import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
import { import {
isNoInstanceConfigWarningModal,
isNoWelcomeModal,
isUserAdminFlagsValid, isUserAdminFlagsValid,
isUserAutoPlayNextVideoValid, isUserAutoPlayNextVideoValid,
isUserAutoPlayVideoValid, isUserAutoPlayVideoValid,
isUserBlockedReasonValid, isUserBlockedReasonValid,
isUserDescriptionValid, isUserDescriptionValid,
isUserDisplayNameValid, isUserDisplayNameValid,
isUserNoModal,
isUserNSFWPolicyValid, isUserNSFWPolicyValid,
isUserPasswordValid, isUserPasswordValid,
isUserPasswordValidOrEmpty, isUserPasswordValidOrEmpty,
@ -251,12 +250,17 @@ const usersUpdateMeValidator = [
body('theme') body('theme')
.optional() .optional()
.custom(v => isThemeNameValid(v) && isThemeRegistered(v)).withMessage('Should have a valid theme'), .custom(v => isThemeNameValid(v) && isThemeRegistered(v)).withMessage('Should have a valid theme'),
body('noInstanceConfigWarningModal') body('noInstanceConfigWarningModal')
.optional() .optional()
.custom(v => isNoInstanceConfigWarningModal(v)).withMessage('Should have a valid noInstanceConfigWarningModal boolean'), .custom(v => isUserNoModal(v)).withMessage('Should have a valid noInstanceConfigWarningModal boolean'),
body('noWelcomeModal') body('noWelcomeModal')
.optional() .optional()
.custom(v => isNoWelcomeModal(v)).withMessage('Should have a valid noWelcomeModal boolean'), .custom(v => isUserNoModal(v)).withMessage('Should have a valid noWelcomeModal boolean'),
body('noAccountSetupWarningModal')
.optional()
.custom(v => isUserNoModal(v)).withMessage('Should have a valid noAccountSetupWarningModal boolean'),
body('autoPlayNextVideo') body('autoPlayNextVideo')
.optional() .optional()
.custom(v => isUserAutoPlayNextVideoValid(v)).withMessage('Should have a valid autoPlayNextVideo boolean'), .custom(v => isUserAutoPlayNextVideoValid(v)).withMessage('Should have a valid autoPlayNextVideo boolean'),

View File

@ -39,8 +39,6 @@ import { UserAdminFlag } from '../../../shared/models/users/user-flag.model'
import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type'
import { isThemeNameValid } from '../../helpers/custom-validators/plugins' import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
import { import {
isNoInstanceConfigWarningModal,
isNoWelcomeModal,
isUserAdminFlagsValid, isUserAdminFlagsValid,
isUserAutoPlayNextVideoPlaylistValid, isUserAutoPlayNextVideoPlaylistValid,
isUserAutoPlayNextVideoValid, isUserAutoPlayNextVideoValid,
@ -48,6 +46,7 @@ import {
isUserBlockedReasonValid, isUserBlockedReasonValid,
isUserBlockedValid, isUserBlockedValid,
isUserEmailVerifiedValid, isUserEmailVerifiedValid,
isUserNoModal,
isUserNSFWPolicyValid, isUserNSFWPolicyValid,
isUserPasswordValid, isUserPasswordValid,
isUserRoleValid, isUserRoleValid,
@ -349,7 +348,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
@Default(false) @Default(false)
@Is( @Is(
'UserNoInstanceConfigWarningModal', 'UserNoInstanceConfigWarningModal',
value => throwIfNotValid(value, isNoInstanceConfigWarningModal, 'no instance config warning modal') value => throwIfNotValid(value, isUserNoModal, 'no instance config warning modal')
) )
@Column @Column
noInstanceConfigWarningModal: boolean noInstanceConfigWarningModal: boolean
@ -357,12 +356,21 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
@AllowNull(false) @AllowNull(false)
@Default(false) @Default(false)
@Is( @Is(
'UserNoInstanceConfigWarningModal', 'UserNoWelcomeModal',
value => throwIfNotValid(value, isNoWelcomeModal, 'no welcome modal') value => throwIfNotValid(value, isUserNoModal, 'no welcome modal')
) )
@Column @Column
noWelcomeModal: boolean noWelcomeModal: boolean
@AllowNull(false)
@Default(false)
@Is(
'UserNoAccountSetupWarningModal',
value => throwIfNotValid(value, isUserNoModal, 'no account setup warning modal')
)
@Column
noAccountSetupWarningModal: boolean
@AllowNull(true) @AllowNull(true)
@Default(null) @Default(null)
@Column @Column
@ -920,6 +928,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
noInstanceConfigWarningModal: this.noInstanceConfigWarningModal, noInstanceConfigWarningModal: this.noInstanceConfigWarningModal,
noWelcomeModal: this.noWelcomeModal, noWelcomeModal: this.noWelcomeModal,
noAccountSetupWarningModal: this.noAccountSetupWarningModal,
blocked: this.blocked, blocked: this.blocked,
blockedReason: this.blockedReason, blockedReason: this.blockedReason,

View File

@ -491,20 +491,20 @@ describe('Test users API validators', function () {
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields }) await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
}) })
it('Should fail with an invalid noInstanceConfigWarningModal attribute', async function () { it('Should fail with invalid no modal attributes', async function () {
const fields = { const keys = [
noInstanceConfigWarningModal: -1 'noInstanceConfigWarningModal',
'noAccountSetupWarningModal',
'noWelcomeModal'
]
for (const key of keys) {
const fields = {
[key]: -1
}
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
} }
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
})
it('Should fail with an invalid noWelcomeModal attribute', async function () {
const fields = {
noWelcomeModal: -1
}
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
}) })
it('Should succeed to change password with the correct params', async function () { it('Should succeed to change password with the correct params', async function () {
@ -516,7 +516,8 @@ describe('Test users API validators', function () {
email: 'super_email@example.com', email: 'super_email@example.com',
theme: 'default', theme: 'default',
noInstanceConfigWarningModal: true, noInstanceConfigWarningModal: true,
noWelcomeModal: true noWelcomeModal: true,
noAccountSetupWarningModal: true
} }
await makePutBodyRequest({ await makePutBodyRequest({

View File

@ -597,6 +597,7 @@ describe('Test users', function () {
expect(user.account.description).to.equal('my super description updated') expect(user.account.description).to.equal('my super description updated')
expect(user.noWelcomeModal).to.be.false expect(user.noWelcomeModal).to.be.false
expect(user.noInstanceConfigWarningModal).to.be.false expect(user.noInstanceConfigWarningModal).to.be.false
expect(user.noAccountSetupWarningModal).to.be.false
}) })
it('Should be able to update my theme', async function () { it('Should be able to update my theme', async function () {
@ -612,12 +613,14 @@ describe('Test users', function () {
await server.users.updateMe({ await server.users.updateMe({
token: userToken, token: userToken,
noInstanceConfigWarningModal: true, noInstanceConfigWarningModal: true,
noWelcomeModal: true noWelcomeModal: true,
noAccountSetupWarningModal: true
}) })
const user = await server.users.getMyInfo({ token: userToken }) const user = await server.users.getMyInfo({ token: userToken })
expect(user.noWelcomeModal).to.be.true expect(user.noWelcomeModal).to.be.true
expect(user.noInstanceConfigWarningModal).to.be.true expect(user.noInstanceConfigWarningModal).to.be.true
expect(user.noAccountSetupWarningModal).to.be.true
}) })
}) })

View File

@ -20,4 +20,5 @@ export interface UserUpdateMe {
noInstanceConfigWarningModal?: boolean noInstanceConfigWarningModal?: boolean
noWelcomeModal?: boolean noWelcomeModal?: boolean
noAccountSetupWarningModal?: boolean
} }

View File

@ -51,6 +51,7 @@ export interface User {
noInstanceConfigWarningModal: boolean noInstanceConfigWarningModal: boolean
noWelcomeModal: boolean noWelcomeModal: boolean
noAccountSetupWarningModal: boolean
createdAt: Date createdAt: Date

View File

@ -6376,6 +6376,8 @@ components:
format: date-time format: date-time
noInstanceConfigWarningModal: noInstanceConfigWarningModal:
type: boolean type: boolean
noAccountSetupWarningModal:
type: boolean
noWelcomeModal: noWelcomeModal:
type: boolean type: boolean
nsfwPolicy: nsfwPolicy:
@ -6530,6 +6532,8 @@ components:
type: string type: string
noInstanceConfigWarningModal: noInstanceConfigWarningModal:
type: boolean type: boolean
noAccountSetupWarningModal:
type: boolean
noWelcomeModal: noWelcomeModal:
type: boolean type: boolean
GetMeVideoRating: GetMeVideoRating: