Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: v1.2.0 maintenance update #21

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 23 additions & 27 deletions .github/workflows/appstore-build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
release:
types: [published]

env:
PHP_VERSION: 8.1

jobs:
build_and_publish:
runs-on: ubuntu-latest
Expand All @@ -21,7 +24,7 @@ jobs:

steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0
uses: skjnldsv/check-actor-permission@e591dbfe838300c007028e1219ca82cc26e8d7c5 # v2.1
with:
require: write

Expand All @@ -32,7 +35,7 @@ jobs:
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV

- name: Checkout
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
path: ${{ env.APP_NAME }}

Expand All @@ -44,19 +47,19 @@ jobs:
expression: "//info//dependencies//nextcloud/@min-version"

- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
# Continue if no package.json
continue-on-error: true
with:
path: ${{ env.APP_NAME }}
fallbackNode: '^20'
fallbackNpm: '^10'
fallbackNode: "^16"
fallbackNpm: "^7"

- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}

Expand All @@ -65,23 +68,17 @@ jobs:
if: ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"

- name: Get php version
id: php-versions
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml

- name: Set up php ${{ steps.php-versions.outputs.php-min }}
uses: shivammathur/setup-php@c665c7a15b5295c2488ac8a87af9cb806cd72198 # v2
- name: Set up php ${{ env.PHP_VERSION }}
uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2
with:
php-version: ${{ steps.php-versions.outputs.php-min }}
php-version: ${{ env.PHP_VERSION }}
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Check composer.json
id: check_composer
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2
with:
files: "${{ env.APP_NAME }}/composer.json"

Expand All @@ -94,16 +91,14 @@ jobs:
- name: Build ${{ env.APP_NAME }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
env:
NODE_ENV: production
run: |
cd ${{ env.APP_NAME }}
npm ci
npm run build --if-present
npm run build

- name: Check Krankerl config
id: krankerl
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2
with:
files: ${{ env.APP_NAME }}/krankerl.toml

Expand Down Expand Up @@ -134,7 +129,7 @@ jobs:
unzip latest-$NCVERSION.zip

- name: Checkout server master fallback
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
if: ${{ steps.server-checkout.outcome != 'success' }}
with:
submodules: true
Expand All @@ -144,24 +139,24 @@ jobs:
- name: Sign app
run: |
# Extracting release
cd ${{ env.APP_NAME }}/build/artifacts
cd ${{ env.APP_NAME }}/build/artifacts/appstore
tar -xvf ${{ env.APP_NAME }}.tar.gz
cd ../../../
cd ../../../../
# Setting up keys
echo "${{ secrets.APP_PRIVATE_KEY }}" > ${{ env.APP_NAME }}.key
wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt"
# Signing
php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}
php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/appstore/${{ env.APP_NAME }}
# Rebuilding archive
cd ${{ env.APP_NAME }}/build/artifacts
cd ${{ env.APP_NAME }}/build/artifacts/appstore
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}

- name: Attach tarball to github release
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2
uses: svenstaro/upload-release-action@2b9d2847a97b04d02ad5c3df2d3a27baa97ce689 # v2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
file: ${{ env.APP_NAME }}/build/artifacts/appstore/${{ env.APP_NAME }}.tar.gz
asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz
tag: ${{ github.ref }}
overwrite: true
Expand All @@ -173,3 +168,4 @@ jobs:
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}

14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [1.2.0 - 2025-01-21]

Maintenance update. NC31 support.

### Added

- Added support of Nextcloud 31

### Changed

- Drop support of NC28, NC29
- Update npm pkgs


## [1.1.0 - 2024-09-16]

Maintenance update
Expand Down
4 changes: 2 additions & 2 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<name>Profile picker</name>
<summary>Profile smart picker and link preview</summary>
<description><![CDATA[This app adds ability to search for user profiles via smart picker and link previews for them.]]></description>
<version>1.1.0</version>
<version>1.2.0</version>
<licence>agpl</licence>
<author mail="[email protected]" homepage="https://github.com/andrey18106">Andrey Borysenko</author>
<namespace>UsersPicker</namespace>
Expand All @@ -19,6 +19,6 @@
<screenshot>https://raw.githubusercontent.com/nextcloud/users_picker/main/screenshots/users_picker_2.png</screenshot>
<screenshot>https://raw.githubusercontent.com/nextcloud/users_picker/main/screenshots/users_picker_3.png</screenshot>
<dependencies>
<nextcloud min-version="28" max-version="30"/>
<nextcloud min-version="30" max-version="31"/>
</dependencies>
</info>
103 changes: 49 additions & 54 deletions lib/Reference/ProfilePickerReferenceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,35 @@

namespace OCA\UsersPicker\Reference;

use OC\Collaboration\Reference\LinkReferenceProvider;
use OCA\UsersPicker\AppInfo\Application;
use OCP\Accounts\IAccountManager;

use OCP\Collaboration\Reference\ADiscoverableReferenceProvider;
use OCP\Collaboration\Reference\IReference;
use OCP\Collaboration\Reference\Reference;

use OCP\Collaboration\Reference\IReference;
use OCP\Contacts\IManager;
use OCP\IL10N;
use OCP\IURLGenerator;

use OCA\UsersPicker\AppInfo\Application;
use OCP\Accounts\IAccountManager;
use OCP\IUserManager;
use Psr\Log\LoggerInterface;
use OCP\Profile\IProfileManager;

class ProfilePickerReferenceProvider extends ADiscoverableReferenceProvider {

private const RICH_OBJECT_TYPE = Application::APP_ID . '_profile';

private ?string $userId;
private IL10N $l10n;
private IURLGenerator $urlGenerator;
private LinkReferenceProvider $linkReferenceProvider;
private IUserManager $userManager;
private IAccountManager $accountManager;
private IManager $contactsManager;
public const RICH_OBJECT_TYPE = 'users_picker_profile';

public function __construct(
IL10N $l10n,
IURLGenerator $urlGenerator,
LinkReferenceProvider $linkReferenceProvider,
IUserManager $userManager,
IAccountManager $accountManager,
IManager $contactsManager,
?string $userId,
private LoggerInterface $logger,
private IL10N $l10n,
private IURLGenerator $urlGenerator,
private IUserManager $userManager,
private IAccountManager $accountManager,
private IProfileManager $profileManager,
private ?string $userId,
) {
$this->userId = $userId;
$this->l10n = $l10n;
$this->urlGenerator = $urlGenerator;
$this->linkReferenceProvider = $linkReferenceProvider;
$this->userManager = $userManager;
$this->accountManager = $accountManager;
$this->contactsManager = $contactsManager;
}

/**
* @inheritDoc
*/
public function getId(): string {
public function getId(): string {
return 'profile_picker';
}

Expand All @@ -66,7 +46,7 @@ public function getTitle(): string {
/**
* @inheritDoc
*/
public function getOrder(): int {
public function getOrder(): int {
return 10;
}

Expand Down Expand Up @@ -94,32 +74,46 @@ public function resolveReference(string $referenceText): ?IReference {

$userId = $this->getObjectId($referenceText);
$user = $this->userManager->get($userId);
$contacts = $this->contactsManager->search($userId, ['UID', 'FN', 'EMAIL'], ['types' => true]);
$this->logger->error('Contancts: ' . json_encode($contacts));

if ($user === null) {
return $this->linkReferenceProvider->resolveReference($referenceText);
return null;
}
if (!$this->profileManager->isProfileEnabled($user)) {
return null;
}
$account = $this->accountManager->getAccount($user);

$currentUser = $this->userManager->get($this->userId);

$reference = new Reference($referenceText);

$userDisplayName = $user->getDisplayName();
$userEmail = $user->getEMailAddress();
$userAvatarUrl = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $userId, 'size' => '64']);

$bio = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_BIOGRAPHY);
$bio = $bio->getScope() !== IAccountManager::SCOPE_PRIVATE ? $bio->getValue() : null;
$headline = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_HEADLINE);
$location = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_ADDRESS);
$website = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_WEBSITE);
$organisation = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_ORGANISATION);
$role = $this->accountManager->getAccount($user)->getProperty(IAccountManager::PROPERTY_ROLE);
$bioProperty = $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY);
$bio = null;
$fullBio = null;
if ($this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_BIOGRAPHY, $user, $currentUser)) {
$fullBio = $bioProperty->getValue();
$bio = $fullBio !== ''
? (mb_strlen($fullBio) > 80
? (mb_substr($fullBio, 0, 80) . '...')
: $fullBio)
: null;
}
$headline = $account->getProperty(IAccountManager::PROPERTY_HEADLINE);
$location = $account->getProperty(IAccountManager::PROPERTY_ADDRESS);
$website = $account->getProperty(IAccountManager::PROPERTY_WEBSITE);
$organisation = $account->getProperty(IAccountManager::PROPERTY_ORGANISATION);
$role = $account->getProperty(IAccountManager::PROPERTY_ROLE);

// for clients who can't render the reference widgets
$reference->setTitle($userDisplayName);
$reference->setDescription($userEmail ?? $userDisplayName);
$reference->setImageUrl($userAvatarUrl);

$isLocationVisible = $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ADDRESS, $user, $currentUser);

// for the Vue reference widget
$reference->setRichObject(
self::RICH_OBJECT_TYPE,
Expand All @@ -128,20 +122,21 @@ public function resolveReference(string $referenceText): ?IReference {
'title' => $userDisplayName,
'subline' => $userEmail ?? $userDisplayName,
'email' => $userEmail,
'bio' => isset($bio) && $bio !== '' ? substr_replace($bio, '...', 80, strlen($bio)) : null,
'headline' => $headline->getScope() !== IAccountManager::SCOPE_PRIVATE ? $headline->getValue() : null,
'location' => $location->getScope() !== IAccountManager::SCOPE_PRIVATE ? $location->getValue() : null,
'location_url' => $location->getScope() !== IAccountManager::SCOPE_PRIVATE ? $this->getOpenStreetLocationUrl($location->getValue()) : null,
'website' => $website->getScope() !== IAccountManager::SCOPE_PRIVATE ? $website->getValue() : null,
'organisation' => $organisation->getScope() !== IAccountManager::SCOPE_PRIVATE ? $organisation->getValue() : null,
'role' => $role->getScope() !== IAccountManager::SCOPE_PRIVATE ? $role->getValue() : null,
'bio' => $bio,
'full_bio' => $fullBio,
'headline' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_HEADLINE, $user, $currentUser) ? $headline->getValue() : null,
'location' => $isLocationVisible ? $location->getValue() : null,
'location_url' => $isLocationVisible ? $this->getOpenStreetLocationUrl($location->getValue()) : null,
'website' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_WEBSITE, $user, $currentUser) ? $website->getValue() : null,
'organisation' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ORGANISATION, $user, $currentUser) ? $organisation->getValue() : null,
'role' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ROLE, $user, $currentUser) ? $role->getValue() : null,
'url' => $referenceText,
]
);
return $reference;
}

private function getObjectId(string $url): ?string {
public function getObjectId(string $url): ?string {
$baseUrl = $this->urlGenerator->getBaseUrl();
$baseWithIndex = $baseUrl . '/index.php';

Expand All @@ -157,7 +152,7 @@ private function getObjectId(string $url): ?string {
return null;
}

private function getOpenStreetLocationUrl($location) {
public function getOpenStreetLocationUrl($location): string {
return 'https://www.openstreetmap.org/search?query=' . urlencode($location);
}

Expand Down
Loading