diff --git a/apps/admin_audit/lib/Actions/Sharing.php b/apps/admin_audit/lib/Actions/Sharing.php
index 2c28660a56f2c7b76a2fa6312f0b69521e6a916e..cab02ab188653546f6164c37028fcc67d37684bf 100644
--- a/apps/admin_audit/lib/Actions/Sharing.php
+++ b/apps/admin_audit/lib/Actions/Sharing.php
@@ -146,6 +146,19 @@ class Sharing extends Action {
 					'id',
 				]
 			);
+		} elseif ($params['shareType'] === IShare::TYPE_DECK) {
+			$this->log(
+				'The %s "%s" with ID "%s" has been shared to the deck card "%s" with permissions "%s" (Share ID: %s)',
+				$params,
+				[
+					'itemType',
+					'itemTarget',
+					'itemSource',
+					'shareWith',
+					'permissions',
+					'id',
+				]
+			);
 		}
 	}
 
@@ -250,6 +263,18 @@ class Sharing extends Action {
 					'id',
 				]
 			);
+		} elseif ($params['shareType'] === IShare::TYPE_DECK) {
+			$this->log(
+				'The %s "%s" with ID "%s" has been unshared from the deck card "%s" (Share ID: %s)',
+				$params,
+				[
+					'itemType',
+					'fileTarget',
+					'itemSource',
+					'shareWith',
+					'id',
+				]
+			);
 		}
 	}
 
diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
index 3abdf6c254694dd3156d18502ca09f32b635bac5..c4b8f0a462390b18890adaf01272072a923290e8 100644
--- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
@@ -121,6 +121,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
 			IShare::TYPE_EMAIL,
 			IShare::TYPE_ROOM,
 			IShare::TYPE_CIRCLE,
+			IShare::TYPE_DECK,
 		];
 		foreach ($requestedShareTypes as $requestedShareType) {
 			$shares = $this->shareManager->getSharesBy(
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index 27af0b1501b4098017a9779440bd65865daba771..f48e652272257b9b85110a0bd4e314350e3c0167 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -276,6 +276,7 @@ class SharesPluginTest extends \Test\TestCase {
 			[[IShare::TYPE_LINK]],
 			[[IShare::TYPE_REMOTE]],
 			[[IShare::TYPE_ROOM]],
+			[[IShare::TYPE_DECK]],
 			[[IShare::TYPE_USER, IShare::TYPE_GROUP]],
 			[[IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK]],
 			[[IShare::TYPE_USER, IShare::TYPE_LINK]],
diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php
index ee4d86bc360961249576cdb37382921a2d9a3ad8..f7a0674eff0f9725f594aff836ac1d4e4d82ec9d 100644
--- a/apps/files/lib/Controller/ApiController.php
+++ b/apps/files/lib/Controller/ApiController.php
@@ -221,7 +221,8 @@ class ApiController extends Controller {
 			IShare::TYPE_LINK,
 			IShare::TYPE_REMOTE,
 			IShare::TYPE_EMAIL,
-			IShare::TYPE_ROOM
+			IShare::TYPE_ROOM,
+			IShare::TYPE_DECK,
 		];
 		foreach ($requestedShareTypes as $requestedShareType) {
 			// one of each type is enough to find out about the types
diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php
index fa979c2006aeba49604d92a616294db5ed116088..bd8520b92fc0bf5b64b1f5701217f405b7dd4f01 100644
--- a/apps/files/lib/Service/OwnershipTransferService.php
+++ b/apps/files/lib/Service/OwnershipTransferService.php
@@ -252,7 +252,7 @@ class OwnershipTransferService {
 
 		$shares = [];
 		$progress = new ProgressBar($output);
-		foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE] as $shareType) {
+		foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE, IShare::TYPE_DECK] as $shareType) {
 			$offset = 0;
 			while (true) {
 				$sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset);
diff --git a/apps/files_sharing/js/dist/additionalScripts.js b/apps/files_sharing/js/dist/additionalScripts.js
index be0ffa5e1bb6c9f396c320de215381bea83fd0c0..f5966ec3cf3f7e31a3369fc63a9e7544914643dd 100644
Binary files a/apps/files_sharing/js/dist/additionalScripts.js and b/apps/files_sharing/js/dist/additionalScripts.js differ
diff --git a/apps/files_sharing/js/dist/additionalScripts.js.map b/apps/files_sharing/js/dist/additionalScripts.js.map
index 0d831ba8549b381024e9f80ac4d1a30472ee2b41..20de1fff9b06dd86164f6ece925f38f7b6515123 100644
Binary files a/apps/files_sharing/js/dist/additionalScripts.js.map and b/apps/files_sharing/js/dist/additionalScripts.js.map differ
diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js b/apps/files_sharing/js/dist/files_sharing_tab.js
index 535431fdd3a2721c4369d848a34e1090405a583b..ca78f9c06bdd7d71f07f4e2607ec558e323a832d 100644
Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js and b/apps/files_sharing/js/dist/files_sharing_tab.js differ
diff --git a/apps/files_sharing/js/dist/files_sharing_tab.js.map b/apps/files_sharing/js/dist/files_sharing_tab.js.map
index 55c2012cee3b0c1c0062e007a2625655e105c6bc..ecd5b302c27d5326700b3f8d99666e92ede21667 100644
Binary files a/apps/files_sharing/js/dist/files_sharing_tab.js.map and b/apps/files_sharing/js/dist/files_sharing_tab.js.map differ
diff --git a/apps/files_sharing/js/dist/main.js b/apps/files_sharing/js/dist/main.js
index 206bc8b9044409bb245cdf70fe7f7f68fea4720f..4995303afe0a59df53dbdb3db9e00413acc061bd 100644
Binary files a/apps/files_sharing/js/dist/main.js and b/apps/files_sharing/js/dist/main.js differ
diff --git a/apps/files_sharing/js/dist/main.js.map b/apps/files_sharing/js/dist/main.js.map
index a50837077297bb1c22d3838ae870433a186bb106..62ae9f2491a4041cdf4b3427930bd364da9684ed 100644
Binary files a/apps/files_sharing/js/dist/main.js.map and b/apps/files_sharing/js/dist/main.js.map differ
diff --git a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
index 9b367e0654416dc28f5f1d6f3ecf6e3ed82fdf46..9a757412316afe26fcc51c0177b6d41b0b10770d 100644
--- a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
@@ -151,6 +151,14 @@ class DeletedShareAPIController extends OCSController {
 				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
 			} catch (QueryException $e) {
 			}
+		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
+			$result['share_with'] = $share->getSharedWith();
+			$result['share_with_displayname'] = '';
+
+			try {
+				$result = array_merge($result, $this->getDeckShareHelper()->formatShare($share));
+			} catch (QueryException $e) {
+			}
 		}
 
 		return $result;
@@ -162,8 +170,9 @@ class DeletedShareAPIController extends OCSController {
 	public function index(): DataResponse {
 		$groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
 		$roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
+		$deckShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_DECK, null, -1, 0);
 
-		$shares = array_merge($groupShares, $roomShares);
+		$shares = array_merge($groupShares, $roomShares, $deckShares);
 
 		$shares = array_map(function (IShare $share) {
 			return $this->formatShare($share);
@@ -211,6 +220,23 @@ class DeletedShareAPIController extends OCSController {
 			throw new QueryException();
 		}
 
-		return $this->serverContainer->query('\OCA\Talk\Share\Helper\DeletedShareAPIController');
+		return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
+	}
+
+	/**
+	 * Returns the helper of ShareAPIHelper for deck shares.
+	 *
+	 * If the Deck application is not enabled or the helper is not available
+	 * a QueryException is thrown instead.
+	 *
+	 * @return \OCA\Deck\Sharing\ShareAPIHelper
+	 * @throws QueryException
+	 */
+	private function getDeckShareHelper() {
+		if (!$this->appManager->isEnabledForUser('deck')) {
+			throw new QueryException();
+		}
+
+		return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
 	}
 }
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index aaca16b32e6cedcd40ed4e3df04615e308f54a2c..65de654be92e636834911121bc42848a23e0c561 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -303,6 +303,14 @@ class ShareAPIController extends OCSController {
 				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
 			} catch (QueryException $e) {
 			}
+		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
+			$result['share_with'] = $share->getSharedWith();
+			$result['share_with_displayname'] = '';
+
+			try {
+				$result = array_merge($result, $this->getDeckShareHelper()->formatShare($share));
+			} catch (QueryException $e) {
+			}
 		}
 
 
@@ -603,6 +611,12 @@ class ShareAPIController extends OCSController {
 			} catch (QueryException $e) {
 				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
 			}
+		} elseif ($shareType === IShare::TYPE_DECK) {
+			try {
+				$this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
+			} catch (QueryException $e) {
+				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
+			}
 		} else {
 			throw new OCSBadRequestException($this->l->t('Unknown share type'));
 		}
@@ -635,8 +649,9 @@ class ShareAPIController extends OCSController {
 		$groupShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_GROUP, $node, -1, 0);
 		$circleShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_CIRCLE, $node, -1, 0);
 		$roomShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_ROOM, $node, -1, 0);
+		$deckShares = $this->shareManager->getSharedWith($this->currentUser, IShare::TYPE_DECK, $node, -1, 0);
 
-		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
+		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares, $deckShares);
 
 		$filteredShares = array_filter($shares, function (IShare $share) {
 			return $share->getShareOwner() !== $this->currentUser;
@@ -1296,6 +1311,14 @@ class ShareAPIController extends OCSController {
 			}
 		}
 
+		if ($share->getShareType() === IShare::TYPE_DECK) {
+			try {
+				return $this->getDeckShareHelper()->canAccessShare($share, $this->currentUser);
+			} catch (QueryException $e) {
+				return false;
+			}
+		}
+
 		return false;
 	}
 
@@ -1371,7 +1394,8 @@ class ShareAPIController extends OCSController {
 	 */
 	protected function canDeleteShareFromSelf(\OCP\Share\IShare $share): bool {
 		if ($share->getShareType() !== IShare::TYPE_GROUP &&
-			$share->getShareType() !== IShare::TYPE_ROOM
+			$share->getShareType() !== IShare::TYPE_ROOM &&
+			$share->getShareType() !== IShare::TYPE_DECK
 		) {
 			return false;
 		}
@@ -1400,6 +1424,14 @@ class ShareAPIController extends OCSController {
 			}
 		}
 
+		if ($share->getShareType() === IShare::TYPE_DECK) {
+			try {
+				return $this->getDeckShareHelper()->canAccessShare($share, $this->currentUser);
+			} catch (QueryException $e) {
+				return false;
+			}
+		}
+
 		return false;
 	}
 
@@ -1474,6 +1506,15 @@ class ShareAPIController extends OCSController {
 			// Do nothing, just try the other share type
 		}
 
+		try {
+			if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) {
+				$share = $this->shareManager->getShareById('deck:' . $id, $this->currentUser);
+				return $share;
+			}
+		} catch (ShareNotFound $e) {
+			// Do nothing, just try the other share type
+		}
+
 		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
 			throw new ShareNotFound();
 		}
@@ -1517,9 +1558,25 @@ class ShareAPIController extends OCSController {
 			throw new QueryException();
 		}
 
-		return $this->serverContainer->query('\OCA\Talk\Share\Helper\ShareAPIController');
+		return $this->serverContainer->get('\OCA\Talk\Share\Helper\ShareAPIController');
 	}
 
+	/**
+	 * Returns the helper of ShareAPIHelper for deck shares.
+	 *
+	 * If the Deck application is not enabled or the helper is not available
+	 * a QueryException is thrown instead.
+	 *
+	 * @return \OCA\Deck\Sharing\ShareAPIHelper
+	 * @throws QueryException
+	 */
+	private function getDeckShareHelper() {
+		if (!$this->appManager->isEnabledForUser('deck')) {
+			throw new QueryException();
+		}
+
+		return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
+	}
 
 	/**
 	 * @param string $viewer
@@ -1536,7 +1593,8 @@ class ShareAPIController extends OCSController {
 			IShare::TYPE_EMAIL,
 			IShare::TYPE_EMAIL,
 			IShare::TYPE_CIRCLE,
-			IShare::TYPE_ROOM
+			IShare::TYPE_ROOM,
+			IShare::TYPE_DECK
 		];
 
 		// Should we assume that the (currentUser) viewer is the owner of the node !?
@@ -1689,6 +1747,8 @@ class ShareAPIController extends OCSController {
 		// TALK SHARES
 		$roomShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_ROOM, $path, $reshares, -1, 0);
 
+		$deckShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_DECK, $path, $reshares, -1, 0);
+
 		// FEDERATION
 		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
 			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, IShare::TYPE_REMOTE, $path, $reshares, -1, 0);
@@ -1701,7 +1761,7 @@ class ShareAPIController extends OCSController {
 			$federatedGroupShares = [];
 		}
 
-		return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $federatedShares, $federatedGroupShares);
+		return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $deckShares, $federatedShares, $federatedGroupShares);
 	}
 
 
diff --git a/apps/files_sharing/lib/Controller/ShareesAPIController.php b/apps/files_sharing/lib/Controller/ShareesAPIController.php
index 0509ba72f1ab951557e4d3be426fad892b304855..a2b39b407724923a723e85725a67919867b233ce 100644
--- a/apps/files_sharing/lib/Controller/ShareesAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareesAPIController.php
@@ -83,6 +83,7 @@ class ShareesAPIController extends OCSController {
 			'emails' => [],
 			'circles' => [],
 			'rooms' => [],
+			'deck' => [],
 		],
 		'users' => [],
 		'groups' => [],
@@ -92,6 +93,7 @@ class ShareesAPIController extends OCSController {
 		'lookup' => [],
 		'circles' => [],
 		'rooms' => [],
+		'deck' => [],
 		'lookupEnabled' => false,
 	];
 
@@ -183,6 +185,10 @@ class ShareesAPIController extends OCSController {
 			if ($this->shareManager->shareProviderExists(IShare::TYPE_ROOM)) {
 				$shareTypes[] = IShare::TYPE_ROOM;
 			}
+
+			if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) {
+				$shareTypes[] = IShare::TYPE_DECK;
+			}
 		} else {
 			$shareTypes[] = IShare::TYPE_GROUP;
 			$shareTypes[] = IShare::TYPE_EMAIL;
@@ -193,6 +199,10 @@ class ShareesAPIController extends OCSController {
 			$shareTypes[] = IShare::TYPE_CIRCLE;
 		}
 
+		if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) {
+			$shareTypes[] = IShare::TYPE_DECK;
+		}
+
 		if ($shareType !== null && is_array($shareType)) {
 			$shareTypes = array_intersect($shareTypes, $shareType);
 		} elseif (is_numeric($shareType)) {
diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php
index 3e703a4a6bb81904eb37d11ad4897c5c81ea1784..3ab3185b95e25499afe083f77b317b014328d9a6 100644
--- a/apps/files_sharing/lib/MountProvider.php
+++ b/apps/files_sharing/lib/MountProvider.php
@@ -78,6 +78,8 @@ class MountProvider implements IMountProvider {
 		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1));
 		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1));
 		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1));
+		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1));
+
 
 		// filter out excluded shares and group shares that includes self
 		$shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) {
diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue
index 55bdbb8fdcb19d4483195714feaa8648d076a7c7..407221037dcb0ee7230bce024a548822195338ad 100644
--- a/apps/files_sharing/src/components/SharingEntry.vue
+++ b/apps/files_sharing/src/components/SharingEntry.vue
@@ -29,13 +29,16 @@
 			:tooltip-message="share.type === SHARE_TYPES.SHARE_TYPE_USER ? share.shareWith : ''"
 			:menu-position="'left'"
 			:url="share.shareWithAvatar" />
-		<div v-tooltip.auto="tooltip" class="sharing-entry__desc">
+		<component :is="share.shareWithLink ? 'a' : 'div'"
+			:href="share.shareWithLink"
+			v-tooltip.auto="tooltip"
+			class="sharing-entry__desc">
 			<h5>{{ title }}</h5>
 			<p v-if="hasStatus">
 				<span>{{ share.status.icon || '' }}</span>
 				<span>{{ share.status.message || '' }}</span>
 			</p>
-		</div>
+		</component>
 		<Actions
 			menu-align="right"
 			class="sharing-entry__actions"
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index 588ed6341663695dddb6a60217c6e74ba090264f..c8373c6c0aee3bd3936975061f5b538f638f0d87 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -186,6 +186,7 @@ export default {
 				this.SHARE_TYPES.SHARE_TYPE_CIRCLE,
 				this.SHARE_TYPES.SHARE_TYPE_ROOM,
 				this.SHARE_TYPES.SHARE_TYPE_GUEST,
+				this.SHARE_TYPES.SHARE_TYPE_DECK,
 			]
 
 			if (OC.getCapabilities().files_sharing.public.enabled === true) {
@@ -365,6 +366,8 @@ export default {
 				return 'icon-circle'
 			case this.SHARE_TYPES.SHARE_TYPE_ROOM:
 				return 'icon-room'
+			case this.SHARE_TYPES.SHARE_TYPE_DECK:
+				return 'icon-deck'
 
 			default:
 				return ''
@@ -384,6 +387,8 @@ export default {
 				desc = t('files_sharing', 'on {server}', { server: result.value.server })
 			} else if (result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_EMAIL) {
 				desc = result.value.shareWith
+			} else {
+				desc = result.shareWithDescription ?? ''
 			}
 
 			return {
diff --git a/apps/files_sharing/src/index.js b/apps/files_sharing/src/index.js
index 786b648aea1c7d74a6a027694ae853f3ba6959b0..3c0d0e65c8f0035d1659f8fe5de03d59fd2565de 100644
--- a/apps/files_sharing/src/index.js
+++ b/apps/files_sharing/src/index.js
@@ -32,5 +32,6 @@ Object.assign(OC, {
 		SHARE_TYPE_GUEST: 8,
 		SHARE_TYPE_REMOTE_GROUP: 9,
 		SHARE_TYPE_ROOM: 10,
+		SHARE_TYPE_DECK: 12,
 	},
 })
diff --git a/apps/files_sharing/src/mixins/ShareTypes.js b/apps/files_sharing/src/mixins/ShareTypes.js
index b84dbf96d98333c49474d9bbf6845d8604a51132..6e9524ce95264f5155cfb83b8bf3f6e49511a2c5 100644
--- a/apps/files_sharing/src/mixins/ShareTypes.js
+++ b/apps/files_sharing/src/mixins/ShareTypes.js
@@ -31,6 +31,7 @@ export default {
 				SHARE_TYPE_REMOTE: OC.Share.SHARE_TYPE_REMOTE,
 				SHARE_TYPE_CIRCLE: OC.Share.SHARE_TYPE_CIRCLE,
 				SHARE_TYPE_GUEST: OC.Share.SHARE_TYPE_GUEST,
+				SHARE_TYPE_DECK: OC.Share.SHARE_TYPE_DECK,
 				SHARE_TYPE_REMOTE_GROUP: OC.Share.SHARE_TYPE_REMOTE_GROUP,
 				SHARE_TYPE_ROOM: OC.Share.SHARE_TYPE_ROOM,
 			},
diff --git a/apps/files_sharing/src/models/Share.js b/apps/files_sharing/src/models/Share.js
index 07f74652a442e47946648ca15167e9c185e01069..d36484f064ac26d9cd156b23eca84242576957d7 100644
--- a/apps/files_sharing/src/models/Share.js
+++ b/apps/files_sharing/src/models/Share.js
@@ -150,6 +150,17 @@ export default class Share {
 			|| this.#share.share_with
 	}
 
+	/**
+	 * Get the share with entity link
+	 *
+	 * @returns {string}
+	 * @readonly
+	 * @memberof Share
+	 */
+	get shareWithLink() {
+		return this.#share.share_with_link
+	}
+
 	/**
 	 * Get the share with avatar if any
 	 *
diff --git a/apps/files_sharing/src/share.js b/apps/files_sharing/src/share.js
index 7d5aeec42249cf16d6bea0799625bbc1aadeca77..47c57e70b6c94243b00dc9a3d3e7a4e722494ffb 100644
--- a/apps/files_sharing/src/share.js
+++ b/apps/files_sharing/src/share.js
@@ -161,6 +161,8 @@ import escapeHTML from 'escape-html'
 								hasShares = true
 							} else if (shareType === OC.Share.SHARE_TYPE_ROOM) {
 								hasShares = true
+							} else if (shareType === OC.Share.SHARE_TYPE_DECK) {
+								hasShares = true
 							}
 						})
 						OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink)
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 1759e532810e57212ba1712fb60498a98645a1ce..a2a6ab59809d81bd19c00abde02f9a1b1509c3bf 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -196,10 +196,10 @@ class ShareAPIControllerTest extends TestCase {
 		$this->expectExceptionMessage('Wrong share ID, share doesn\'t exist');
 
 		$this->shareManager
-			->expects($this->exactly(5))
+			->expects($this->exactly(6))
 			->method('getShareById')
 			->willReturnCallback(function ($id) {
-				if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42') {
+				if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42') {
 					throw new \OCP\Share\Exceptions\ShareNotFound();
 				} else {
 					throw new \Exception();
@@ -1558,7 +1558,7 @@ class ShareAPIControllerTest extends TestCase {
 				->with($share, $this->currentUser)
 				->willReturn($canAccessShareByHelper);
 
-			$this->serverContainer->method('query')
+			$this->serverContainer->method('get')
 				->with('\OCA\Talk\Share\Helper\ShareAPIController')
 				->willReturn($helper);
 		}
@@ -2222,7 +2222,7 @@ class ShareAPIControllerTest extends TestCase {
 				}
 			);
 
-		$this->serverContainer->method('query')
+		$this->serverContainer->method('get')
 			->with('\OCA\Talk\Share\Helper\ShareAPIController')
 			->willReturn($helper);
 
@@ -2340,7 +2340,7 @@ class ShareAPIControllerTest extends TestCase {
 				}
 			);
 
-		$this->serverContainer->method('query')
+		$this->serverContainer->method('get')
 			->with('\OCA\Talk\Share\Helper\ShareAPIController')
 			->willReturn($helper);
 
@@ -4404,7 +4404,7 @@ class ShareAPIControllerTest extends TestCase {
 				->with($share)
 				->willReturn($formatShareByHelper);
 
-			$this->serverContainer->method('query')
+			$this->serverContainer->method('get')
 				->with('\OCA\Talk\Share\Helper\ShareAPIController')
 				->willReturn($helper);
 		}
diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php
index c7116230813a447d7d6a2b834a6fd910be27579f..f40bd44331e5d45134c8ef1823c6d981b5ba3976 100644
--- a/apps/files_sharing/tests/MountProviderTest.php
+++ b/apps/files_sharing/tests/MountProviderTest.php
@@ -123,6 +123,12 @@ class MountProviderTest extends \Test\TestCase {
 			$this->makeMockShare(8, 102, 'user2', '/share6', 31),
 			$this->makeMockShare(9, 102, 'user2', '/share6', 31),
 		];
+		$deckShares = [
+			$this->makeMockShare(10, 103, 'user2', '/share7', 0),
+			$this->makeMockShare(11, 103, 'user1', '/share7', 31),
+			$this->makeMockShare(12, 103, 'user2', '/share7', 31),
+			$this->makeMockShare(13, 103, 'user2', '/share7', 31),
+		];
 		// tests regarding circles are made in the app itself.
 		$circleShares = [];
 		$this->user->expects($this->any())
@@ -144,16 +150,21 @@ class MountProviderTest extends \Test\TestCase {
 			->method('getSharedWith')
 			->with('user1', IShare::TYPE_ROOM, null, -1)
 			->willReturn($roomShares);
+		$this->shareManager->expects($this->at(4))
+			->method('getSharedWith')
+			->with('user1', IShare::TYPE_DECK, null, -1)
+			->willReturn($deckShares);
 		$this->shareManager->expects($this->any())
 			->method('newShare')
 			->willReturnCallback(function () use ($rootFolder, $userManager) {
 				return new \OC\Share20\Share($rootFolder, $userManager);
 			});
 		$mounts = $this->provider->getMountsForUser($this->user, $this->loader);
-		$this->assertCount(3, $mounts);
+		$this->assertCount(4, $mounts);
 		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]);
 		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]);
 		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]);
+		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[3]);
 		$mountedShare1 = $mounts[0]->getShare();
 		$this->assertEquals('2', $mountedShare1->getId());
 		$this->assertEquals('user2', $mountedShare1->getShareOwner());
@@ -172,6 +183,12 @@ class MountProviderTest extends \Test\TestCase {
 		$this->assertEquals(102, $mountedShare3->getNodeId());
 		$this->assertEquals('/share6', $mountedShare3->getTarget());
 		$this->assertEquals(31, $mountedShare3->getPermissions());
+		$mountedShare4 = $mounts[3]->getShare();
+		$this->assertEquals('12', $mountedShare4->getId());
+		$this->assertEquals('user2', $mountedShare4->getShareOwner());
+		$this->assertEquals(103, $mountedShare4->getNodeId());
+		$this->assertEquals('/share7', $mountedShare4->getTarget());
+		$this->assertEquals(31, $mountedShare4->getPermissions());
 	}
 
 	public function mergeSharesDataProvider() {
@@ -337,6 +354,7 @@ class MountProviderTest extends \Test\TestCase {
 		// tests regarding circles are made in the app itself.
 		$circleShares = [];
 		$roomShares = [];
+		$deckShares = [];
 		$this->shareManager->expects($this->at(0))
 			->method('getSharedWith')
 			->with('user1', IShare::TYPE_USER)
@@ -353,6 +371,10 @@ class MountProviderTest extends \Test\TestCase {
 			->method('getSharedWith')
 			->with('user1', IShare::TYPE_ROOM, null, -1)
 			->willReturn($roomShares);
+		$this->shareManager->expects($this->at(4))
+			->method('getSharedWith')
+			->with('user1', IShare::TYPE_DECK, null, -1)
+			->willReturn($deckShares);
 		$this->shareManager->expects($this->any())
 			->method('newShare')
 			->willReturnCallback(function () use ($rootFolder, $userManager) {
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 68690455ad37d8f05206459943af3e3e35c628c3..cdbd0dc677154bc2b5bf497b39cd38f5abc31fd5 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -1613,12 +1613,6 @@
       <code>getUserFolder</code>
     </UndefinedInterfaceMethod>
   </file>
-  <file src="apps/files_sharing/lib/Controller/DeletedShareAPIController.php">
-    <UndefinedDocblockClass occurrences="2">
-      <code>$this-&gt;getRoomShareHelper()</code>
-      <code>\OCA\Talk\Share\Helper\DeletedShareAPIController</code>
-    </UndefinedDocblockClass>
-  </file>
   <file src="apps/files_sharing/lib/Controller/ShareAPIController.php">
     <InvalidScalarArgument occurrences="3">
       <code>$code</code>
@@ -5051,16 +5045,13 @@
       <code>FederatedShareProvider</code>
       <code>ShareByMailProvider</code>
     </InvalidNullableReturnType>
-    <InvalidReturnStatement occurrences="5">
+    <InvalidReturnStatement occurrences="4">
       <code>$provider</code>
       <code>$provider</code>
-      <code>$shares</code>
       <code>$this-&gt;roomShareProvider</code>
       <code>$this-&gt;shareByCircleProvider</code>
     </InvalidReturnStatement>
-    <InvalidReturnType occurrences="3">
-      <code>getAllProviders</code>
-      <code>getProvider</code>
+    <InvalidReturnType occurrences="1">
       <code>getProviderForType</code>
     </InvalidReturnType>
     <NullableReturnStatement occurrences="6">
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index 2310859c5bebb35fd08cae41adc6b3a3cb179f14..77ed31762770b82a537219ed919c6402e6e59923 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -70,6 +70,11 @@ class Constants {
 	 */
 	public const SHARE_TYPE_ROOM = 10;
 	// const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
+	/**
+	 * @deprecated 21.0.0 - use IShare::TYPE_DECK instead
+	 */
+	public const SHARE_TYPE_DECK = 12;
+	// const SHARE_TYPE_DECK_USER = 13; // Internal type used by DeckShareProvider
 
 	public const FORMAT_NONE = -1;
 	public const FORMAT_STATUSES = -2;
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index e9895edf95aeefb564b7315da170c37b4daa5c25..6b782237b8c454499384b7f1db465c473d42d85d 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -248,6 +248,7 @@ class Manager implements IManager {
 				throw new \InvalidArgumentException('SharedWith is not a valid circle');
 			}
 		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
+		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
 		} else {
 			// We can't handle other types yet
 			throw new \InvalidArgumentException('unknown share type');
@@ -1887,6 +1888,10 @@ class Manager implements IManager {
 		return true;
 	}
 
+	public function registerShareProvider(string $shareProviderClass): void {
+		$this->factory->registerProvider($shareProviderClass);
+	}
+
 	public function getAllShares(): iterable {
 		$providers = $this->factory->getAllProviders();
 
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 2d4c4e6d40a5cb4f4acb2e3ad610f4cf98897917..9f93df46ac042a624171f860bee17e6cdcdb8bfd 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -44,6 +44,7 @@ use OCP\EventDispatcher\IEventDispatcher;
 use OCP\IServerContainer;
 use OCP\Share\IProviderFactory;
 use OCP\Share\IShare;
+use OCP\Share\IShareProvider;
 
 /**
  * Class ProviderFactory
@@ -67,6 +68,10 @@ class ProviderFactory implements IProviderFactory {
 	/** @var \OCA\Talk\Share\RoomShareProvider */
 	private $roomShareProvider = null;
 
+	private $registeredShareProviders = [];
+
+	private $shareProviders = [];
+
 	/**
 	 * IProviderFactory constructor.
 	 *
@@ -76,6 +81,10 @@ class ProviderFactory implements IProviderFactory {
 		$this->serverContainer = $serverContainer;
 	}
 
+	public function registerProvider(string $shareProviderClass): void {
+		$this->registeredShareProviders[] = $shareProviderClass;
+	}
+
 	/**
 	 * Create the default share provider.
 	 *
@@ -257,6 +266,10 @@ class ProviderFactory implements IProviderFactory {
 	 */
 	public function getProvider($id) {
 		$provider = null;
+		if (isset($this->shareProviders[$id])) {
+			return $this->shareProviders[$id];
+		}
+
 		if ($id === 'ocinternal') {
 			$provider = $this->defaultShareProvider();
 		} elseif ($id === 'ocFederatedSharing') {
@@ -269,6 +282,16 @@ class ProviderFactory implements IProviderFactory {
 			$provider = $this->getRoomShareProvider();
 		}
 
+		foreach ($this->registeredShareProviders as $shareProvider) {
+			/** @var IShareProvider $instance */
+			$instance = $this->serverContainer->get($shareProvider);
+			$this->shareProviders[$instance->identifier()] = $instance;
+		}
+
+		if (isset($this->shareProviders[$id])) {
+			$provider = $this->shareProviders[$id];
+		}
+
 		if ($provider === null) {
 			throw new ProviderException('No provider with id .' . $id . ' found.');
 		}
@@ -295,6 +318,8 @@ class ProviderFactory implements IProviderFactory {
 			$provider = $this->getShareByCircleProvider();
 		} elseif ($shareType === IShare::TYPE_ROOM) {
 			$provider = $this->getRoomShareProvider();
+		} elseif ($shareType === IShare::TYPE_DECK) {
+			$provider = $this->getProvider('deck');
 		}
 
 
@@ -320,6 +345,17 @@ class ProviderFactory implements IProviderFactory {
 			$shares[] = $roomShare;
 		}
 
+		foreach ($this->registeredShareProviders as $shareProvider) {
+			/** @var IShareProvider $instance */
+			$instance = $this->serverContainer->get($shareProvider);
+			if (!isset($this->shareProviders[$instance->identifier()])) {
+				$this->shareProviders[$instance->identifier()] = $instance;
+			}
+			$shares[] = $this->shareProviders[$instance->identifier()];
+		}
+
+
+
 		return $shares;
 	}
 }
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index cc2ec45cc9f994f1c0f79a57dc44aba44e6d4fbc..635ccc1483d68d264d10db67f6b2968e3cfa7499 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -416,6 +416,12 @@ interface IManager {
 	 */
 	public function shareProviderExists($shareType);
 
+	/**
+	 * @param string $shareProviderClass
+	 * @since 21.0.0
+	 */
+	public function registerShareProvider(string $shareProviderClass): void;
+
 	/**
 	 * @Internal
 	 *
diff --git a/lib/public/Share/IProviderFactory.php b/lib/public/Share/IProviderFactory.php
index 27218497e53099c91782900080831715d61c3fbf..480837404f01d5f0bba05f53048a36dda98720c4 100644
--- a/lib/public/Share/IProviderFactory.php
+++ b/lib/public/Share/IProviderFactory.php
@@ -53,4 +53,10 @@ interface IProviderFactory {
 	 * @since 11.0.0
 	 */
 	public function getAllProviders();
+
+	/**
+	 * @since 21.0.0
+	 * @param string $shareProvier
+	 */
+	public function registerProvider(string $shareProvier): void;
 }
diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php
index 7b38e00df46215b5b7a77e751e1c05cb55eed9bd..86aceba80f5326ae18bee1825e2a4dbd5ec389da 100644
--- a/lib/public/Share/IShare.php
+++ b/lib/public/Share/IShare.php
@@ -105,6 +105,17 @@ interface IShare {
 	 */
 	// const TYPE_USERROOM = 11;
 
+	/**
+	 * @since 21.0.0
+	 */
+	public const TYPE_DECK = 12;
+
+	/**
+	 * @internal
+	 * @since 21.0.0
+	 */
+	public const TYPE_DECK_USER = 13;
+
 	/**
 	 * @since 18.0.0
 	 */
diff --git a/psalm.xml b/psalm.xml
index b90af78022a8b9c8d66be987cc2ce2111d9a22b2..0706f566829ee6ef783df5d6856320c32707ee4d 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -85,5 +85,12 @@
 				<file name="core/register_command.php" />
 			</errorLevel>
 		</UndefinedGlobalVariable>
+		<UndefinedDocblockClass>
+			<errorLevel type="suppress">
+				<!-- Helper classes for sharing API integration from other apps -->
+				<referencedClass name="OCA\Deck\Sharing\ShareAPIHelper" />
+				<referencedClass name="OCA\Talk\Share\Helper\DeletedShareAPIController" />
+			</errorLevel>
+		</UndefinedDocblockClass>
 	</issueHandlers>
 </psalm>
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 65313858c01d751067b4b14f5926c680ad8ef249..efae909b99f32c3e0832ad71a5cfe54ab5f250a5 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -4362,6 +4362,9 @@ class DummyFactory implements IProviderFactory {
 	public function getAllProviders() {
 		return [$this->provider];
 	}
+
+	public function registerProvider(string $shareProvier): void {
+	}
 }
 
 class DummyFactory2 extends DummyFactory {
@@ -4378,4 +4381,7 @@ class DummyFactory2 extends DummyFactory {
 	public function getAllProviders() {
 		return [$this->provider, $this->provider2];
 	}
+
+	public function registerProvider(string $shareProvier): void {
+	}
 }