Skip to content

Commit

Permalink
[WHIP]
Browse files Browse the repository at this point in the history
- Provide icons as URLs instead of CSS classes
- Add entrypoint to contacts menu as displayname link and as action
- Add entrypoint to Avatar component in Talk through contacts menu actions provider (propagates to everything which uses ContactsMenuController)
- Use helper function to check if the profile is enabled
- Handle disabled profile state for contacts menu and Avatar entrypoints
- General design, UX, and other improvements
- Some cleanup

Signed-off-by: Christopher Ng <chrng8@gmail.com>
  • Loading branch information
Pytal committed Sep 17, 2021
1 parent a968452 commit e3f286d
Show file tree
Hide file tree
Showing 30 changed files with 480 additions and 166 deletions.
16 changes: 3 additions & 13 deletions apps/settings/lib/Settings/Personal/PersonalInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
use OCP\AppFramework\Services\IInitialState;

class PersonalInfo implements ISettings {
use \OC\Accounts\TAccountsHelper;

/** @var IConfig */
private $config;
Expand Down Expand Up @@ -158,7 +159,7 @@ public function getForm(): TemplateResponse {
'displayNameMap' => $this->getDisplayNameMap($account),
'emailMap' => $this->getEmailMap($account),
'languageMap' => $this->getLanguageMap($user),
'profileEnabled' => $this->getProfileEnabled($account),
'profileEnabled' => $this->isProfileEnabled($account),
'companyMap' => $this->getCompanyMap($account),
'jobTitleMap' => $this->getJobTitleMap($account),
'headlineMap' => $this->getHeadlineMap($account),
Expand Down Expand Up @@ -307,7 +308,7 @@ private function getDisplayNameMap(IAccount $account): array {
* returns the primary email and additional emails in an
* associative array
*/
private function getEmails(IAccount $account): array {
private function getEmailMap(IAccount $account): array {
$systemEmail = [
'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(),
'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(),
Expand Down Expand Up @@ -434,15 +435,4 @@ private function getMessageParameters(IAccount $account): array {
}
return $messageParameters;
}

/**
* returns the profile enabled state
*/
private function getProfileEnabled(IAccount $account): bool {
return filter_var(
$account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import Email from './Email'
import HeaderBar from '../shared/HeaderBar'
import { ACCOUNT_PROPERTY_READABLE_ENUM, DEFAULT_ADDITIONAL_EMAIL_SCOPE } from '../../../constants/AccountPropertyConstants'
import { savePrimaryEmail, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService'
import { savePrimaryEmail, savePrimaryEmailScope, removeAdditionalEmail } from '../../../service/PersonalInfo/EmailService'
import { validateEmail } from '../../../utils/validate'
const { emailMap: { additionalEmails, primaryEmail, notificationEmail } } = loadState('settings', 'personalInfoParameters', {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
:user="userId"
:size="48"
:show-user-status="true"
:show-user-status-compact="true"
:show-user-status-compact="false"
:disable-menu="true"
:disable-tooltip="true"
@click.native.prevent.stop="openStatusModal" />
Expand Down Expand Up @@ -87,7 +87,7 @@ export default {
profilePageLink() {
if (this.profileEnabled) {
return generateUrl('u/{userId}', { userId: getCurrentUser().uid })
return generateUrl('/u/{userId}', { userId: getCurrentUser().uid })
}
// Since an anchor element is used rather than a button for better UX,
// this hack removes href if the profile is disabled so that disabling pointer-events is not needed to prevent a click from opening a page
Expand Down Expand Up @@ -115,14 +115,14 @@ export default {
box-shadow: 0 2px 9px var(--color-box-shadow);
&:hover {
box-shadow: 0 2px 10px rgba(77, 77, 77, 0.65);
box-shadow: 0 2px 12px var(--color-box-shadow);
}
&.disabled {
filter: grayscale(1);
opacity: 0.5;
cursor: default;
box-shadow: 0 2px 9px rgba(77, 77, 77, 0.1);
box-shadow: 0 0 3px var(--color-box-shadow);
& *,
&::v-deep * {
Expand Down
14 changes: 7 additions & 7 deletions apps/settings/src/constants/AccountPropertyConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ export const ACCOUNT_SETTING_PROPERTY_READABLE_ENUM = Object.freeze({

/** Enum of scopes */
export const SCOPE_ENUM = Object.freeze({
LOCAL: 'v2-local',
PRIVATE: 'v2-private',
LOCAL: 'v2-local',
FEDERATED: 'v2-federated',
PUBLISHED: 'v2-published',
})
Expand Down Expand Up @@ -126,18 +126,18 @@ export const SCOPE_SUFFIX = 'Scope'
* *Used for federation control*
*/
export const SCOPE_PROPERTY_ENUM = Object.freeze({
[SCOPE_ENUM.LOCAL]: {
name: SCOPE_ENUM.LOCAL,
displayName: t('settings', 'Local'),
tooltip: t('settings', 'Only visible to people on this instance and guests'),
iconClass: 'icon-password',
},
[SCOPE_ENUM.PRIVATE]: {
name: SCOPE_ENUM.PRIVATE,
displayName: t('settings', 'Private'),
tooltip: t('settings', 'Only visible to people matched via phone number integration through Talk on mobile'),
iconClass: 'icon-phone',
},
[SCOPE_ENUM.LOCAL]: {
name: SCOPE_ENUM.LOCAL,
displayName: t('settings', 'Local'),
tooltip: t('settings', 'Only visible to people on this instance and guests'),
iconClass: 'icon-password',
},
[SCOPE_ENUM.FEDERATED]: {
name: SCOPE_ENUM.FEDERATED,
displayName: t('settings', 'Federated'),
Expand Down
23 changes: 3 additions & 20 deletions apps/user_status/lib/Listener/BeforeTemplateRenderedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\UserStatus\Listener;

use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\IUserSession;
use OCA\UserStatus\AppInfo\Application;
use OCA\UserStatus\Service\JSDataService;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IInitialStateService;
use OCP\User\Events\BeforeUserLoggedInEvent;
use OCP\User\Events\PostLoginEvent;
use OCP\User\Events\UserLiveStatusEvent;

class BeforeTemplateRenderedListener implements IEventListener {
use \OC\Accounts\TAccountsHelper;

/** @var IAccountManager */
private $accountManager;
Expand Down Expand Up @@ -99,24 +96,10 @@ public function handle(Event $event): void {
});

$this->initialState->provideLazyInitialState(Application::APP_ID, 'profileEnabled', function () use ($account) {
return ['profileEnabled' => $this->getProfileEnabled($account)];
return ['profileEnabled' => $this->isProfileEnabled($account)];
});

\OCP\Util::addScript('user_status', 'user-status-menu');
\OCP\Util::addStyle('user_status', 'user-status-menu');
}

/**
* returns the profile enabled state
*
* @param IAccount $account
* @return bool
*/
private function getProfileEnabled(IAccount $account): bool {
return filter_var(
$account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
);
}
}
52 changes: 20 additions & 32 deletions core/Controller/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
// use OCP\IL10N;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Profile\IActionManager;
use OCP\Profile\IProfileAction;
use OCP\UserStatus\IManager as IUserStatusManager;
use Psr\Container\ContainerInterface;

class ProfileController extends Controller {

Expand All @@ -59,12 +57,6 @@ class ProfileController extends Controller {
/** @var TrustedServers */
private $trustedServers;

/** @var IL10N */
// private $l10n;

/** @var ContainerInterface */
// private $containerInterface;

/** @var IUserSession */
private $userSession;

Expand All @@ -89,30 +81,26 @@ class ProfileController extends Controller {
public function __construct(
$appName,
IRequest $request,
// IL10N $l10n,
ContainerInterface $containerInterface,
IURLGenerator $urlGenerator,
TrustedServers $trustedServers,
IUserSession $userSession,
IUserManager $userManager,
IAccountManager $accountManager,
IInitialState $initialStateService,
IActionManager $actionManager,
IAppManager $appManager,
IInitialState $initialStateService,
IURLGenerator $urlGenerator,
IUserManager $userManager,
IUserSession $userSession,
IUserStatusManager $userStatusManager,
IActionManager $actionManager
TrustedServers $trustedServers
) {
parent::__construct($appName, $request);
// $this->l10n = $l10n;
$this->containerInterface = $containerInterface;
$this->urlGenerator = $urlGenerator;
$this->trustedServers = $trustedServers;
$this->userSession = $userSession;
$this->userManager = $userManager;
$this->accountManager = $accountManager;
$this->initialStateService = $initialStateService;
$this->actionManager = $actionManager;
$this->appManager = $appManager;
$this->initialStateService = $initialStateService;
$this->trustedServers = $trustedServers;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
$this->userSession = $userSession;
$this->userStatusManager = $userStatusManager;
$this->actionManager = $actionManager;
}

public const PROFILE_DISPLAY_PROPERTIES = [
Expand Down Expand Up @@ -140,16 +128,14 @@ public function __construct(
IAccountManager::PROPERTY_TWITTER,
];

/**
* Useful annotations
* @NoAdminRequired
*/

/**
* FIXME Public page annotation blocks the user session somehow
*
* @PublicPage
* @UseSession
* @NoCSRFRequired
* @NoAdminRequired
* @NoSubAdminRequired
*/
public function index(string $userId): TemplateResponse {
if (!$this->userManager->userExists($userId)) {
Expand All @@ -169,7 +155,7 @@ public function index(string $userId): TemplateResponse {
FILTER_NULL_ON_FAILURE,
);

if (empty($profileEnabled)) {
if (!$profileEnabled) {
return new TemplateResponse(
'core',
'404-page',
Expand Down Expand Up @@ -292,6 +278,7 @@ protected function initActions(IAccount $account) {
$isLoggedIn = $this->userSession->isLoggedIn();
$userId = $account->getUser()->getUID();
$talkEnabled = $this->appManager->isEnabledForUser('spreed', $account->getUser());
// $talkEnabled = false;

if ($talkEnabled) {
$this->actionManager->registerAction(TalkAction::class, $userId);
Expand All @@ -301,10 +288,10 @@ protected function initActions(IAccount $account) {
$scope = $account->getProperty($property)->getScope();
$value = $account->getProperty($property)->getValue();

// The other less strict scopes all allow public link access
if ($scope === IAccountManager::SCOPE_PRIVATE && !$isLoggedIn) {
return;
continue;
}
// The other less strict scopes all allow public link access

if (!empty($value)) {
switch ($property) {
Expand Down Expand Up @@ -332,6 +319,7 @@ function (IProfileAction $action) {
'name' => $action->getName(),
'icon' => $action->getIcon(),
'title' => $action->getTitle(),
'label' => $action->getLabel(),
'target' => $action->getTarget(),
];
},
Expand Down
8 changes: 8 additions & 0 deletions core/css/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,14 @@ span.ui-icon {

/* ---- TOOLTIPS ---- */

body {
div:last-child {
&.bs-tooltip-right {
left: -10px !important;
}
}
}

.extra-data {
padding-right: 5px !important;
}
Expand Down
1 change: 1 addition & 0 deletions core/img/actions/phone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion core/img/actions/profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions core/img/actions/timezone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions core/img/actions/twitter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions core/src/OC/contactsmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ const ContactsListItemView = View.extend({
// Show placeholder if no avatar is available (avatar is rendered as img, not div)
this.$('div.avatar').imageplaceholder(this._model.get('fullName'))

// Show tooltip for profile link
this.$('.profile-link--avatar').tooltip({ placement: 'left' })
this.$('.profile-link--full-name').tooltip({ placement: 'left' })

// Show tooltip for top action
this.$('.top-action').tooltip({ placement: 'left' })
// Show tooltip for second action
Expand Down
40 changes: 33 additions & 7 deletions core/src/OC/contactsmenu/contact.handlebars
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
{{#if contact.avatar}}
<img src="{{contact.avatar}}&size=32" class="avatar" srcset="{{contact.avatar}}&size=32 1x, {{contact.avatar}}&size=64 2x, {{contact.avatar}}&size=128 4x" alt="">
{{#if contact.profileUrl}}
{{#if contact.profileTitle}}
<a class="profile-link--avatar" title="{{contact.profileTitle}}" href="{{contact.profileUrl}}">
<img src="{{contact.avatar}}&size=32" class="avatar" srcset="{{contact.avatar}}&size=32 1x, {{contact.avatar}}&size=64 2x, {{contact.avatar}}&size=128 4x" alt="">
</a>
{{/if}}
{{else}}
<img src="{{contact.avatar}}&size=32" class="avatar" srcset="{{contact.avatar}}&size=32 1x, {{contact.avatar}}&size=64 2x, {{contact.avatar}}&size=128 4x" alt="">
{{/if}}
{{else}}
<div class="avatar"></div>
{{#if contact.profileUrl}}
{{#if contact.profileTitle}}
<a class="profile-link--avatar" title="{{contact.profileTitle}}" href="{{contact.profileUrl}}">
<div class="avatar"></div>
</a>
{{/if}}
{{else}}
<div class="avatar"></div>
{{/if}}
{{/if}}
{{#if contact.profileUrl}}
{{#if contact.profileTitle}}
<a class="body profile-link--full-name" title="{{contact.profileTitle}}" href="{{contact.profileUrl}}">
<div class="full-name">{{contact.fullName}}</div>
<div class="last-message">{{contact.lastMessage}}</div>
<div class="email-address">{{contact.emailAddresses}}</div>
</a>
{{/if}}
{{else}}
<div class="body">
<div class="full-name">{{contact.fullName}}</div>
<div class="last-message">{{contact.lastMessage}}</div>
<div class="email-address">{{contact.emailAddresses}}</div>
</div>
{{/if}}
<div class="body">
<div class="full-name">{{contact.fullName}}</div>
<div class="last-message">{{contact.lastMessage}}</div>
<div class="email-address">{{contact.emailAddresses}}</div>
</div>
{{#if contact.topAction}}
<a class="top-action" href="{{contact.topAction.hyperlink}}" title="{{contact.topAction.title}}">
<img src="{{contact.topAction.icon}}" alt="{{contact.topAction.title}}">
Expand Down
Loading

0 comments on commit e3f286d

Please sign in to comment.