chromium/chrome/browser/resources/ash/settings/os_people_page/user_list.ts

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview
 * 'settings-user-list' shows a list of users allowed on this Chrome OS
 * device.
 *
 * Example:
 *
 *    <settings-user-list prefs="{{prefs}}">
 *    </settings-user-list>
 */

import 'chrome://resources/ash/common/cr_elements/cr_icon_button/cr_icon_button.js';
import 'chrome://resources/ash/common/cr_elements/icons.html.js';
import 'chrome://resources/ash/common/cr_elements/cr_shared_vars.css.js';
import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
import '../settings_shared.css.js';
import '../settings_vars.css.js';

import {CrA11yAnnouncerElement, getInstance as getAnnouncerInstance} from 'chrome://resources/ash/common/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {CrScrollableMixin} from 'chrome://resources/ash/common/cr_elements/cr_scrollable_mixin.js';
import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js';
import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {RouteObserverMixin} from '../common/route_observer_mixin.js';
import {Router, routes} from '../router.js';

import {getTemplate} from './user_list.html.js';

declare global {
  interface HTMLElementEventMap {
    'all-managed-users-removed': CustomEvent<void>;
  }
}

const SettingsUserListElementBase =
    RouteObserverMixin(I18nMixin(CrScrollableMixin(PolymerElement)));


export class SettingsUserListElement extends SettingsUserListElementBase {
  static get is() {
    return 'settings-user-list' as const;
  }

  static get template() {
    return getTemplate();
  }

  static get properties() {
    return {
      /**
       * Current list of allowed users.
       */
      users_: {
        type: Array,
        value() {
          return [];
        },
        notify: true,
      },

      /**
       * Whether the user list is disabled, i.e. that no modifications can be
       * made.
       */
      disabled: {
        type: Boolean,
        value: false,
        reflectToAttribute: true,
      },
    };
  }

  disabled: boolean;
  private users_: chrome.usersPrivate.User[];
  private usersPrivate_: typeof chrome.usersPrivate;

  constructor() {
    super();

    this.usersPrivate_ = chrome.usersPrivate;
  }

  override ready(): void {
    super.ready();

    chrome.settingsPrivate.onPrefsChanged.addListener(
        (prefs: chrome.settingsPrivate.PrefObject[]) => {
          prefs.forEach((pref: chrome.settingsPrivate.PrefObject) => {
            if (pref.key === 'cros.accounts.users') {
              this.usersPrivate_.getUsers().then(
                  (users: chrome.usersPrivate.User[]) => {
                    this.setUsers_(users);
                  });
            }
          }, this);
        });
  }

  override currentRouteChanged(): void {
    if (Router.getInstance().currentRoute === routes.ACCOUNTS) {
      this.usersPrivate_.getUsers().then(
          (users: chrome.usersPrivate.User[]) => {
            this.setUsers_(users);
          });
    }
  }

  private getUserName_(user: chrome.usersPrivate.User): string {
    return user.isOwner ? this.i18n('deviceOwnerLabel', user.name) : user.name;
  }

  private setUsers_(users: chrome.usersPrivate.User[]): void {
    this.users_ = users;
    this.users_.sort((a, b) => {
      if (a.isOwner !== b.isOwner) {
        return b.isOwner ? 1 : -1;
      } else {
        return -1;
      }
    });
    this.requestUpdateScroll();
  }

  private removeUser_(e: DomRepeatEvent<chrome.usersPrivate.User>): void {
    (getAnnouncerInstance() as CrA11yAnnouncerElement)
        .announce(this.i18n('userRemovedMessage', e.model.item.name));

    // Focus the add user button since, after this removal, the only user left
    // will be the account owner.
    if (this.users_.length === 2) {
      const event = new CustomEvent(
          'all-managed-users-removed', {bubbles: true, composed: true});
      this.dispatchEvent(event);
    }

    this.usersPrivate_.removeUser(e.model.item.email);
  }

  private shouldHideCloseButton_(disabled: boolean, isUserOwner: boolean):
      boolean {
    return disabled || isUserOwner;
  }

  private getProfilePictureUrl_(user: chrome.usersPrivate.User): string {
    return 'chrome://userimage/' + user.email + '?id=' + Date.now() +
        '&frame=0';
  }

  private shouldShowEmail_(user: chrome.usersPrivate.User): boolean {
    return !user.isChild && user.name !== user.displayEmail;
  }

  /**
   * Use this function to prevent tooltips from displaying for user names. We
   * only want to display tooltips for email addresses.
   */
  private getTooltip_(user: chrome.usersPrivate.User): string {
    return !this.shouldShowEmail_(user) ? user.displayEmail : '';
  }

  private getRemoveUserTooltip_(user: chrome.usersPrivate.User): string {
    return this.i18n('removeUserTooltip', user.name);
  }
}

declare global {
  interface HTMLElementTagNameMap {
    [SettingsUserListElement.is]: SettingsUserListElement;
  }
}

customElements.define(SettingsUserListElement.is, SettingsUserListElement);