diff --git a/Telegram/SourceFiles/base/lambda_guard.h b/Telegram/SourceFiles/base/lambda_guard.h
index 5c897bef94..dd997dcd1c 100644
--- a/Telegram/SourceFiles/base/lambda_guard.h
+++ b/Telegram/SourceFiles/base/lambda_guard.h
@@ -21,9 +21,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include <QPointer>
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
-// Guard lambda call by QObject* or enable_weak_from_this* pointers.
+// Guard lambda call by QObject* or has_weak_ptr* pointers.
 
 namespace base {
 namespace lambda_internal {
@@ -66,9 +66,9 @@ class guard_with_weak {
 public:
 	template <typename OtherLambda>
 	guard_with_weak(
-		const base::enable_weak_from_this *object,
+		const base::has_weak_ptr *object,
 		OtherLambda &&other)
-	: _guard(base::make_weak_unique(object))
+	: _guard(base::make_weak(object))
 	, _callable(std::forward<OtherLambda>(other)) {
 	}
 
@@ -91,7 +91,7 @@ public:
 	}
 
 private:
-	base::weak_unique_ptr<const base::enable_weak_from_this> _guard;
+	base::weak_ptr<const base::has_weak_ptr> _guard;
 	Lambda _callable;
 
 };
@@ -117,7 +117,7 @@ inline auto lambda_guarded(const QObject *object, Lambda &&lambda) {
 
 template <typename Lambda>
 inline auto lambda_guarded(
-		const base::enable_weak_from_this *object,
+		const base::has_weak_ptr *object,
 		Lambda &&lambda) {
 	using Guarded = lambda_internal::guard_with_weak<
 		std::decay_t<Lambda>>;
diff --git a/Telegram/SourceFiles/base/weak_ptr.h b/Telegram/SourceFiles/base/weak_ptr.h
new file mode 100644
index 0000000000..6f6d3c6da5
--- /dev/null
+++ b/Telegram/SourceFiles/base/weak_ptr.h
@@ -0,0 +1,302 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
+*/
+#pragma once
+
+#include <atomic>
+
+namespace base {
+namespace details {
+
+struct alive_tracker {
+	std::atomic<int> counter = 1;
+	std::atomic<bool> dead = false;
+};
+
+inline alive_tracker *check_and_increment(alive_tracker *tracker) noexcept {
+	if (tracker) {
+		++tracker->counter;
+	}
+	return tracker;
+}
+
+inline void decrement(alive_tracker *tracker) noexcept {
+	if (tracker->counter.fetch_sub(1) == 0) {
+		delete tracker;
+	}
+}
+
+} // namespace details
+
+class has_weak_ptr;
+
+template <typename T>
+class weak_ptr;
+
+class has_weak_ptr {
+public:
+	has_weak_ptr() = default;
+	has_weak_ptr(const has_weak_ptr &other) noexcept {
+	}
+	has_weak_ptr(has_weak_ptr &&other) noexcept {
+	}
+	has_weak_ptr &operator=(const has_weak_ptr &other) noexcept {
+		return *this;
+	}
+	has_weak_ptr &operator=(has_weak_ptr &&other) noexcept {
+		return *this;
+	}
+
+	~has_weak_ptr() {
+		if (auto alive = _alive.load()) {
+			alive->dead.store(true);
+			details::decrement(alive);
+		}
+	}
+
+private:
+	template <typename Child>
+	friend class weak_ptr;
+
+	details::alive_tracker *incrementAliveTracker() const {
+		auto current = _alive.load();
+		if (!current) {
+			auto alive = std::make_unique<details::alive_tracker>();
+			if (_alive.compare_exchange_strong(current, alive.get())) {
+				return alive.release();
+			}
+		}
+		++current->counter;
+		return current;
+	}
+
+	mutable std::atomic<details::alive_tracker*> _alive = nullptr;
+
+};
+
+template <typename T>
+class weak_ptr {
+public:
+	weak_ptr() = default;
+	weak_ptr(T *value)
+	: _alive(value ? value->incrementAliveTracker() : nullptr)
+	, _value(value) {
+	}
+	weak_ptr(const std::unique_ptr<T> &value)
+	: weak_ptr(value.get()) {
+	}
+	weak_ptr(const std::shared_ptr<T> &value)
+	: weak_ptr(value.get()) {
+	}
+	weak_ptr(const std::weak_ptr<T> &value)
+	: weak_ptr(value.lock().get()) {
+	}
+	weak_ptr(const weak_ptr &other) noexcept
+	: _alive(details::check_and_increment(other._alive))
+	, _value(other._value) {
+	}
+	weak_ptr(weak_ptr &&other) noexcept
+	: _alive(std::exchange(other._alive, nullptr))
+	, _value(std::exchange(other._value, nullptr)) {
+	}
+	template <
+		typename Other,
+		typename = std::enable_if_t<
+			std::is_base_of_v<T, Other> && !std::is_same_v<T, Other>>>
+	weak_ptr(const weak_ptr<Other> &other) noexcept
+	: _alive(details::check_and_increment(other._alive))
+	, _value(other._value) {
+	}
+	template <
+		typename Other,
+		typename = std::enable_if_t<
+			std::is_base_of_v<T, Other> && !std::is_same_v<T, Other>>>
+	weak_ptr(weak_ptr<Other> &&other) noexcept
+	: _alive(std::exchange(other._alive, nullptr))
+	, _value(std::exchange(other._value, nullptr)) {
+	}
+
+	weak_ptr &operator=(T *value) {
+		reset(value);
+		return *this;
+	}
+	weak_ptr &operator=(const std::unique_ptr<T> &value) {
+		reset(value.get());
+		return *this;
+	}
+	weak_ptr &operator=(const std::shared_ptr<T> &value) {
+		reset(value.get());
+		return *this;
+	}
+	weak_ptr &operator=(const std::weak_ptr<T> &value) {
+		reset(value.lock().get());
+		return *this;
+	}
+	weak_ptr &operator=(const weak_ptr &other) noexcept {
+		if (_value != other._value) {
+			destroy();
+			_alive = details::check_and_increment(other._alive);
+			_value = other._value;
+		}
+		return *this;
+	}
+	weak_ptr &operator=(weak_ptr &&other) noexcept {
+		if (_value != other._value) {
+			destroy();
+			_alive = std::exchange(other._alive, nullptr);
+			_value = std::exchange(other._value, nullptr);
+		}
+		return *this;
+	}
+	template <
+		typename Other,
+		typename = std::enable_if_t<
+			std::is_base_of_v<T, Other> && !std::is_same_v<T, Other>>>
+	weak_ptr &operator=(const weak_ptr<Other> &other) noexcept {
+		if (_value != other._value) {
+			destroy();
+			_alive = details::check_and_increment(other._alive);
+			_value = other._value;
+		}
+		return *this;
+	}
+	template <
+		typename Other,
+		typename = std::enable_if_t<
+			std::is_base_of_v<T, Other> && !std::is_same_v<T, Other>>>
+	weak_ptr &operator=(weak_ptr<Other> &&other) noexcept {
+		if (_value != other._value) {
+			destroy();
+			_alive = std::exchange(other._alive, nullptr);
+			_value = std::exchange(other._value, nullptr);
+		}
+		return *this;
+	}
+
+	~weak_ptr() {
+		destroy();
+	}
+
+	T *get() const noexcept {
+		return (_alive && !_alive->dead) ? _value : nullptr;
+	}
+	explicit operator bool() const noexcept {
+		return (_alive && !_alive->dead);
+	}
+	T &operator*() const noexcept {
+		return *get();
+	}
+	T *operator->() const noexcept {
+		return get();
+	}
+
+	void reset(T *value = nullptr) {
+		if (_value != value) {
+			destroy();
+			_alive = value ? value->incrementAliveTracker() : nullptr;
+			_value = value;
+		}
+	}
+
+private:
+	void destroy() noexcept {
+		if (_alive) {
+			details::decrement(_alive);
+		}
+	}
+
+	details::alive_tracker *_alive = nullptr;
+	T *_value = nullptr;
+
+	template <typename Other>
+	friend class weak_ptr;
+
+};
+
+template <typename T>
+inline bool operator==(const weak_ptr<T> &pointer, std::nullptr_t) noexcept {
+	return (pointer.get() == nullptr);
+}
+
+template <typename T>
+inline bool operator==(std::nullptr_t, const weak_ptr<T> &pointer) noexcept {
+	return (pointer == nullptr);
+}
+
+template <typename T>
+inline bool operator!=(const weak_ptr<T> &pointer, std::nullptr_t) noexcept {
+	return !(pointer == nullptr);
+}
+
+template <typename T>
+inline bool operator!=(std::nullptr_t, const weak_ptr<T> &pointer) noexcept {
+	return !(pointer == nullptr);
+}
+
+template <
+	typename T,
+	typename = std::enable_if_t<std::is_base_of_v<has_weak_ptr, T>>>
+weak_ptr<T> make_weak(T *value) {
+	return value;
+}
+
+template <
+	typename T,
+	typename = std::enable_if_t<std::is_base_of_v<has_weak_ptr, T>>>
+weak_ptr<T> make_weak(const std::unique_ptr<T> &value) {
+	return value;
+}
+
+template <
+	typename T,
+	typename = std::enable_if_t<std::is_base_of_v<has_weak_ptr, T>>>
+weak_ptr<T> make_weak(const std::shared_ptr<T> &value) {
+	return value;
+}
+
+template <
+	typename T,
+	typename = std::enable_if_t<std::is_base_of_v<has_weak_ptr, T>>>
+weak_ptr<T> make_weak(const std::weak_ptr<T> &value) {
+	return value;
+}
+
+} // namespace base
+
+#ifdef QT_VERSION
+template <typename Lambda>
+inline void InvokeQueued(const base::has_weak_ptr *context, Lambda &&lambda) {
+	auto callback = [
+		guard = base::make_weak(context),
+		lambda = std::forward<Lambda>(lambda)
+	] {
+		if (guard) {
+			lambda();
+		}
+	};
+	QObject proxy;
+	QObject::connect(
+		&proxy,
+		&QObject::destroyed,
+		QCoreApplication::instance(),
+		std::move(callback),
+		Qt::QueuedConnection);
+}
+#endif // QT_VERSION
diff --git a/Telegram/SourceFiles/base/weak_unique_ptr.h b/Telegram/SourceFiles/base/weak_unique_ptr.h
deleted file mode 100644
index d16ff02d92..0000000000
--- a/Telegram/SourceFiles/base/weak_unique_ptr.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-This file is part of Telegram Desktop,
-the official desktop version of Telegram messaging app, see https://telegram.org
-
-Telegram Desktop is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-It is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-In addition, as a special exception, the copyright holders give permission
-to link the code of portions of this program with the OpenSSL library.
-
-Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
-Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
-*/
-#pragma once
-
-namespace base {
-
-class enable_weak_from_this;
-
-template <typename T>
-class weak_unique_ptr;
-
-class enable_weak_from_this {
-public:
-	enable_weak_from_this() = default;
-	enable_weak_from_this(const enable_weak_from_this &other) noexcept {
-	}
-	enable_weak_from_this(enable_weak_from_this &&other) noexcept {
-	}
-	enable_weak_from_this &operator=(const enable_weak_from_this &other) noexcept {
-		return *this;
-	}
-	enable_weak_from_this &operator=(enable_weak_from_this &&other) noexcept {
-		return *this;
-	}
-
-private:
-	template <typename Child>
-	friend class weak_unique_ptr;
-
-	std::shared_ptr<enable_weak_from_this*> getGuarded() const {
-		if (!_guarded) {
-			_guarded = std::make_shared<enable_weak_from_this*>(
-				const_cast<enable_weak_from_this*>(
-					static_cast<const enable_weak_from_this*>(this)));
-		}
-		return _guarded;
-	}
-
-	mutable std::shared_ptr<enable_weak_from_this*> _guarded;
-
-};
-
-template <typename T>
-class weak_unique_ptr {
-public:
-	weak_unique_ptr() = default;
-	weak_unique_ptr(T *value)
-	: _guarded(value
-		? value->getGuarded()
-		: std::shared_ptr<enable_weak_from_this*>()) {
-	}
-	weak_unique_ptr(const std::unique_ptr<T> &value)
-	: weak_unique_ptr(value.get()) {
-	}
-
-	weak_unique_ptr &operator=(T *value) {
-		_guarded = value
-			? value->getGuarded()
-			: std::shared_ptr<enable_weak_from_this*>();
-		return *this;
-	}
-	weak_unique_ptr &operator=(const std::unique_ptr<T> &value) {
-		return (*this = value.get());
-	}
-
-	T *get() const noexcept {
-		if (auto shared = _guarded.lock()) {
-			return static_cast<T*>(*shared);
-		}
-		return nullptr;
-	}
-	explicit operator bool() const noexcept {
-		return !!_guarded.lock();
-	}
-	T &operator*() const noexcept {
-		return *get();
-	}
-	T *operator->() const noexcept {
-		return get();
-	}
-
-private:
-	std::weak_ptr<enable_weak_from_this*> _guarded;
-
-};
-
-template <typename T>
-inline bool operator==(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
-	return (pointer.get() == nullptr);
-}
-
-template <typename T>
-inline bool operator==(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
-	return (pointer == nullptr);
-}
-
-template <typename T>
-inline bool operator!=(const weak_unique_ptr<T> &pointer, std::nullptr_t) {
-	return !(pointer == nullptr);
-}
-
-template <typename T>
-inline bool operator!=(std::nullptr_t, const weak_unique_ptr<T> &pointer) {
-	return !(pointer == nullptr);
-}
-
-template <typename T>
-weak_unique_ptr<T> make_weak_unique(T *value) {
-	return weak_unique_ptr<T>(value);
-}
-
-template <typename T>
-weak_unique_ptr<T> make_weak_unique(const std::unique_ptr<T> &value) {
-	return weak_unique_ptr<T>(value);
-}
-
-} // namespace base
-
-#ifdef QT_VERSION
-template <typename Lambda>
-inline void InvokeQueued(base::enable_weak_from_this *context, Lambda &&lambda) {
-	QObject proxy;
-	QObject::connect(&proxy, &QObject::destroyed, QCoreApplication::instance(), [guard = base::make_weak_unique(context), lambda = std::forward<Lambda>(lambda)] {
-		if (guard) {
-			lambda();
-		}
-	}, Qt::QueuedConnection);
-}
-#endif // QT_VERSION
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
index c7544bcd69..adff1a7677 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
@@ -725,8 +725,7 @@ void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
 }
 
 void AddBotToGroupBoxController::shareBotGame(not_null<PeerData*> chat) {
-	auto weak = base::make_weak_unique(this);
-	auto send = [weak, bot = _bot, chat] {
+	auto send = [weak = base::make_weak(this), bot = _bot, chat] {
 		if (!weak) {
 			return;
 		}
@@ -773,8 +772,7 @@ void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
 			return;
 		}
 	}
-	auto weak = base::make_weak_unique(this);
-	auto send = [weak, bot = _bot, chat] {
+	auto send = [weak = base::make_weak(this), bot = _bot, chat] {
 		if (!weak) {
 			return;
 		}
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h
index 55be1dbd16..ab42e7848c 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.h
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 
 #include "boxes/peer_list_box.h"
 #include "base/flat_set.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
 // Not used for now.
 //
@@ -207,7 +207,7 @@ private:
 
 };
 
-class AddBotToGroupBoxController : public ChatsListBoxController, public base::enable_weak_from_this {
+class AddBotToGroupBoxController : public ChatsListBoxController, public base::has_weak_ptr {
 public:
 	static void Start(not_null<UserData*> bot);
 
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
index 8c3925e6e3..434544b3cc 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
@@ -52,7 +52,7 @@ constexpr auto kUsernameCheckTimeout = TimeMs(200);
 
 class Controller
 	: private MTP::Sender
-	, private base::enable_weak_from_this {
+	, private base::has_weak_ptr {
 public:
 	Controller(
 		not_null<BoxContent*> box,
diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h
index 447463b37c..f681bdf1a4 100644
--- a/Telegram/SourceFiles/calls/calls_call.h
+++ b/Telegram/SourceFiles/calls/calls_call.h
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "base/timer.h"
 #include "mtproto/sender.h"
 #include "mtproto/auth_key.h"
@@ -43,7 +43,7 @@ struct DhConfig {
 	std::vector<gsl::byte> p;
 };
 
-class Call : public base::enable_weak_from_this, private MTP::Sender {
+class Call : public base::has_weak_ptr, private MTP::Sender {
 public:
 	class Delegate {
 	public:
diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp
index 9bb9447f8f..35ec378ebb 100644
--- a/Telegram/SourceFiles/calls/calls_instance.cpp
+++ b/Telegram/SourceFiles/calls/calls_instance.cpp
@@ -134,7 +134,11 @@ void Instance::createCall(not_null<UserData*> user, Call::Type type) {
 
 void Instance::refreshDhConfig() {
 	Expects(_currentCall != nullptr);
-	request(MTPmessages_GetDhConfig(MTP_int(_dhConfig.version), MTP_int(Call::kRandomPowerSize))).done([this, call = base::make_weak_unique(_currentCall)](const MTPmessages_DhConfig &result) {
+	request(MTPmessages_GetDhConfig(
+		MTP_int(_dhConfig.version),
+		MTP_int(Call::kRandomPowerSize)
+	)).done([this, call = base::make_weak(_currentCall)](
+			const MTPmessages_DhConfig &result) {
 		auto random = base::const_byte_span();
 		switch (result.type()) {
 		case mtpc_messages_dhConfig: {
@@ -170,7 +174,8 @@ void Instance::refreshDhConfig() {
 		if (call) {
 			call->start(random);
 		}
-	}).fail([this, call = base::make_weak_unique(_currentCall)](const RPCError &error) {
+	}).fail([this, call = base::make_weak(_currentCall)](
+			const RPCError &error) {
 		if (!call) {
 			DEBUG_LOG(("API Warning: call was destroyed before got dhConfig."));
 			return;
diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h
index 9ceb37ce07..d950b0254a 100644
--- a/Telegram/SourceFiles/calls/calls_panel.h
+++ b/Telegram/SourceFiles/calls/calls_panel.h
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "base/timer.h"
 #include "calls/calls_call.h"
 #include "ui/widgets/tooltip.h"
diff --git a/Telegram/SourceFiles/calls/calls_top_bar.cpp b/Telegram/SourceFiles/calls/calls_top_bar.cpp
index 77c6e3614e..40cbdcefa6 100644
--- a/Telegram/SourceFiles/calls/calls_top_bar.cpp
+++ b/Telegram/SourceFiles/calls/calls_top_bar.cpp
@@ -39,7 +39,7 @@ constexpr auto kUpdateDebugTimeoutMs = TimeMs(500);
 
 class DebugInfoBox : public BoxContent {
 public:
-	DebugInfoBox(QWidget*, base::weak_unique_ptr<Call> call);
+	DebugInfoBox(QWidget*, base::weak_ptr<Call> call);
 
 protected:
 	void prepare() override;
@@ -47,13 +47,14 @@ protected:
 private:
 	void updateText();
 
-	base::weak_unique_ptr<Call> _call;
+	base::weak_ptr<Call> _call;
 	QPointer<Ui::FlatLabel> _text;
 	base::Timer _updateTextTimer;
 
 };
 
-DebugInfoBox::DebugInfoBox(QWidget*, base::weak_unique_ptr<Call> call) : _call(call) {
+DebugInfoBox::DebugInfoBox(QWidget*, base::weak_ptr<Call> call)
+: _call(call) {
 }
 
 void DebugInfoBox::prepare() {
@@ -82,7 +83,7 @@ void DebugInfoBox::updateText() {
 
 TopBar::TopBar(
 	QWidget *parent,
-	const base::weak_unique_ptr<Call> &call)
+	const base::weak_ptr<Call> &call)
 : RpWidget(parent)
 , _call(call)
 , _durationLabel(this, st::callBarLabel)
diff --git a/Telegram/SourceFiles/calls/calls_top_bar.h b/Telegram/SourceFiles/calls/calls_top_bar.h
index 11b6fe7bcb..786499870c 100644
--- a/Telegram/SourceFiles/calls/calls_top_bar.h
+++ b/Telegram/SourceFiles/calls/calls_top_bar.h
@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "base/timer.h"
 #include "ui/rp_widget.h"
 
@@ -37,7 +37,7 @@ class Call;
 
 class TopBar : public Ui::RpWidget, private base::Subscriber {
 public:
-	TopBar(QWidget *parent, const base::weak_unique_ptr<Call> &call);
+	TopBar(QWidget *parent, const base::weak_ptr<Call> &call);
 
 	~TopBar();
 
@@ -54,7 +54,7 @@ private:
 	void startDurationUpdateTimer(TimeMs currentDuration);
 	void setMuted(bool mute);
 
-	base::weak_unique_ptr<Call> _call;
+	base::weak_ptr<Call> _call;
 
 	bool _muted = false;
 	object_ptr<Ui::LabelSimple> _durationLabel;
diff --git a/Telegram/SourceFiles/data/data_shared_media.h b/Telegram/SourceFiles/data/data_shared_media.h
index 74fe0f0e3e..59ce8c34aa 100644
--- a/Telegram/SourceFiles/data/data_shared_media.h
+++ b/Telegram/SourceFiles/data/data_shared_media.h
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "storage/storage_shared_media.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "data/data_sparse_ids.h"
 
 base::optional<Storage::SharedMediaType> SharedMediaOverviewType(
diff --git a/Telegram/SourceFiles/data/data_user_photos.h b/Telegram/SourceFiles/data/data_user_photos.h
index a38a17743b..632e67ae66 100644
--- a/Telegram/SourceFiles/data/data_user_photos.h
+++ b/Telegram/SourceFiles/data/data_user_photos.h
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "storage/storage_user_photos.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
 class UserPhotosSlice {
 public:
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
index 2a41ae83dd..bd9569313c 100644
--- a/Telegram/SourceFiles/facades.h
+++ b/Telegram/SourceFiles/facades.h
@@ -69,7 +69,7 @@ inline void CallDelayed(
 template <typename Lambda>
 inline void CallDelayed(
 		int duration,
-		const base::enable_weak_from_this *object,
+		const base::has_weak_ptr *object,
 		Lambda &&lambda) {
 	return internal::CallDelayed(
 		duration,
@@ -93,7 +93,7 @@ inline auto LambdaDelayed(
 template <typename Lambda>
 inline auto LambdaDelayed(
 		int duration,
-		const base::enable_weak_from_this *object,
+		const base::has_weak_ptr *object,
 		Lambda &&lambda) {
 	auto guarded = base::lambda_guarded(
 		object,
@@ -120,7 +120,7 @@ inline auto LambdaDelayedOnce(
 template <typename Lambda>
 inline auto LambdaDelayedOnce(
 		int duration,
-		const base::enable_weak_from_this *object,
+		const base::has_weak_ptr *object,
 		Lambda &&lambda) {
 	auto guarded = base::lambda_guarded(
 		object,
diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
index f6e5dea5a0..31218eccbc 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
+++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "info/profile/info_profile_members_controllers.h"
 
 #include <rpl/variable.h>
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "profile/profile_channel_controllers.h"
 #include "ui/widgets/popup_menu.h"
 #include "lang/lang_keys.h"
@@ -42,7 +42,7 @@ constexpr auto kSortByOnlineDelay = TimeMs(1000);
 class ChatMembersController
 	: public PeerListController
 	, private base::Subscriber
-	, public base::enable_weak_from_this {
+	, public base::has_weak_ptr {
 public:
 	ChatMembersController(
 		not_null<Window::Controller*> window,
@@ -286,7 +286,7 @@ Ui::PopupMenu *ChatMembersController::rowContextMenu(
 	auto result = new Ui::PopupMenu(nullptr);
 	result->addAction(
 		lang(lng_context_view_profile),
-		[weak = base::make_weak_unique(this), user] {
+		[weak = base::make_weak(this), user] {
 			if (weak) {
 				weak->_window->showPeerInfo(user);
 			}
@@ -294,7 +294,7 @@ Ui::PopupMenu *ChatMembersController::rowContextMenu(
 	if (canRemoveMember) {
 		result->addAction(
 			lang(lng_context_remove_from_group),
-			[weak = base::make_weak_unique(this), user] {
+			[weak = base::make_weak(this), user] {
 				if (weak) {
 					weak->removeMember(user);
 				}
diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp
index 45a3cb1042..23dbbc30d1 100644
--- a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp
+++ b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp
@@ -244,7 +244,7 @@ void CloudManager::switchToLanguage(QString id) {
 void CloudManager::performSwitchToCustom() {
 	auto filter = qsl("Language files (*.strings)");
 	auto title = qsl("Choose language .strings file");
-	FileDialog::GetOpenPath(title, filter, [weak = base::make_weak_unique(this)](const FileDialog::OpenResult &result) {
+	FileDialog::GetOpenPath(title, filter, [weak = base::make_weak(this)](const FileDialog::OpenResult &result) {
 		if (!weak || result.paths.isEmpty()) {
 			return;
 		}
diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.h b/Telegram/SourceFiles/lang/lang_cloud_manager.h
index d272502e7d..d57ed5f797 100644
--- a/Telegram/SourceFiles/lang/lang_cloud_manager.h
+++ b/Telegram/SourceFiles/lang/lang_cloud_manager.h
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "mtproto/sender.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
 namespace MTP {
 class Instance;
@@ -31,7 +31,7 @@ namespace Lang {
 
 class Instance;
 
-class CloudManager : public base::enable_weak_from_this, private MTP::Sender, private base::Subscriber {
+class CloudManager : public base::has_weak_ptr, private MTP::Sender, private base::Subscriber {
 public:
 	CloudManager(Instance &langpack, not_null<MTP::Instance*> mtproto);
 
diff --git a/Telegram/SourceFiles/lang/lang_instance.h b/Telegram/SourceFiles/lang/lang_instance.h
index e676507063..2ae7bb311d 100644
--- a/Telegram/SourceFiles/lang/lang_instance.h
+++ b/Telegram/SourceFiles/lang/lang_instance.h
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 
 #include <rpl/producer.h>
 #include "lang_auto.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
 namespace Lang {
 
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index 3e5616d7a0..d9f6425539 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -23,7 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "storage/localimageloader.h"
 #include "history/history_common.h"
 #include "core/single_timer.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "ui/rp_widget.h"
 
 namespace Notify {
@@ -583,7 +583,7 @@ private:
 	object_ptr<Window::SectionWidget> _thirdSection = { nullptr };
 	std::unique_ptr<Window::SectionMemento> _thirdSectionFromStack;
 
-	base::weak_unique_ptr<Calls::Call> _currentCall;
+	base::weak_ptr<Calls::Call> _currentCall;
 	object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
 
 	object_ptr<Window::PlayerWrapWidget> _player = { nullptr };
diff --git a/Telegram/SourceFiles/mtproto/config_loader.cpp b/Telegram/SourceFiles/mtproto/config_loader.cpp
index e8ae79ece4..90062ff585 100644
--- a/Telegram/SourceFiles/mtproto/config_loader.cpp
+++ b/Telegram/SourceFiles/mtproto/config_loader.cpp
@@ -142,16 +142,15 @@ void ConfigLoader::sendSpecialRequest() {
 		return;
 	}
 
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	auto index = rand_value<uint32>() % uint32(_specialEndpoints.size());
 	auto endpoint = _specialEndpoints.begin() + index;
 	_specialEnumCurrent = specialToRealDcId(endpoint->dcId);
 	_instance->dcOptions()->constructAddOne(_specialEnumCurrent, MTPDdcOption::Flag::f_tcpo_only, endpoint->ip, endpoint->port);
 	_specialEnumRequest = _instance->send(MTPhelp_GetConfig(), rpcDone([weak](const MTPConfig &result) {
-		if (!weak) {
-			return;
+		if (const auto strong = weak.get()) {
+			strong->specialConfigLoaded(result);
 		}
-		weak->specialConfigLoaded(result);
 	}), _failHandler, _specialEnumCurrent);
 	_triedSpecialEndpoints.push_back(*endpoint);
 	_specialEndpoints.erase(endpoint);
diff --git a/Telegram/SourceFiles/mtproto/config_loader.h b/Telegram/SourceFiles/mtproto/config_loader.h
index 9d4c708558..10cb869b8f 100644
--- a/Telegram/SourceFiles/mtproto/config_loader.h
+++ b/Telegram/SourceFiles/mtproto/config_loader.h
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "base/timer.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "mtproto/rpc_sender.h"
 
 namespace MTP {
@@ -31,7 +31,7 @@ class Instance;
 
 namespace internal {
 
-class ConfigLoader : public base::enable_weak_from_this {
+class ConfigLoader : public base::has_weak_ptr {
 public:
 	ConfigLoader(not_null<Instance*> instance, RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail);
 	~ConfigLoader();
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
index 57c79cd98c..bb7c993c68 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
@@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #pragma once
 
 #include "platform/platform_notifications_manager.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 
 namespace Platform {
 namespace Notifications {
@@ -29,7 +29,7 @@ namespace Notifications {
 bool SkipAudio();
 bool SkipToast();
 
-class Manager : public Window::Notifications::NativeManager, public base::enable_weak_from_this {
+class Manager : public Window::Notifications::NativeManager, public base::has_weak_ptr {
 public:
 	Manager(Window::Notifications::System *system);
 	~Manager();
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
index d6e8e5d92b..4c20192b84 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
@@ -61,19 +61,19 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm);
 @interface NotificationDelegate : NSObject<NSUserNotificationCenterDelegate> {
 }
 
-- (id) initWithManager:(base::weak_unique_ptr<Manager>)manager managerId:(uint64)managerId;
+- (id) initWithManager:(base::weak_ptr<Manager>)manager managerId:(uint64)managerId;
 - (void) userNotificationCenter:(NSUserNotificationCenter*)center didActivateNotification:(NSUserNotification*)notification;
 - (BOOL) userNotificationCenter:(NSUserNotificationCenter*)center shouldPresentNotification:(NSUserNotification*)notification;
 
 @end // @interface NotificationDelegate
 
 @implementation NotificationDelegate {
-	base::weak_unique_ptr<Manager> _manager;
+	base::weak_ptr<Manager> _manager;
 	uint64 _managerId;
 
 }
 
-- (id) initWithManager:(base::weak_unique_ptr<Manager>)manager managerId:(uint64)managerId {
+- (id) initWithManager:(base::weak_ptr<Manager>)manager managerId:(uint64)managerId {
 	if (self = [super init]) {
 		_manager = manager;
 		_managerId = managerId;
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
index bce692c6f7..9ae316c476 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp
@@ -216,14 +216,14 @@ void ParticipantsBoxController::addNewItem() {
 		}
 		return;
 	}
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	_addBox = Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantBoxController>(_channel, _role, [weak](not_null<UserData*> user, const MTPChannelAdminRights &rights) {
-		if (weak) {
-			weak->editAdminDone(user, rights);
+		if (const auto strong = weak.get()) {
+			strong->editAdminDone(user, rights);
 		}
 	}, [weak](not_null<UserData*> user, const MTPChannelBannedRights &rights) {
-		if (weak) {
-			weak->editRestrictedDone(user, rights);
+		if (const auto strong = weak.get()) {
+			strong->editRestrictedDone(user, rights);
 		}
 	}), [](not_null<PeerListBox*> box) {
 		box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
@@ -640,9 +640,9 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 	auto result = new Ui::PopupMenu(nullptr);
 	result->addAction(
 		lang(lng_context_view_profile),
-		[weak = base::make_weak_unique(this), user] {
-			if (weak) {
-				weak->_window->showPeerInfo(user);
+		[weak = base::make_weak(this), user] {
+			if (const auto strong = weak.get()) {
+				strong->_window->showPeerInfo(user);
 			}
 		});
 	if (canEditAdmin(user)) {
@@ -654,9 +654,9 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 			: lng_context_edit_permissions);
 		result->addAction(
 			label,
-			[weak = base::make_weak_unique(this), user] {
-				if (weak) {
-					weak->showAdmin(user);
+			[weak = base::make_weak(this), user] {
+				if (const auto strong = weak.get()) {
+					strong->showAdmin(user);
 				}
 			});
 	}
@@ -665,9 +665,9 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 		if (isGroup) {
 			result->addAction(
 				lang(lng_context_restrict_user),
-				[weak = base::make_weak_unique(this), user]{
-					if (weak) {
-						weak->showRestricted(user);
+				[weak = base::make_weak(this), user]{
+					if (const auto strong = weak.get()) {
+						strong->showRestricted(user);
 					}
 				});
 		}
@@ -675,9 +675,9 @@ Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
 			lang(isGroup
 				? lng_context_remove_from_group
 				: lng_profile_kick),
-			[weak = base::make_weak_unique(this), user] {
-				if (weak) {
-					weak->kickMember(user);
+			[weak = base::make_weak(this), user] {
+				if (auto strong = weak.get()) {
+					strong->kickMember(user);
 				}
 			});
 	}
@@ -691,7 +691,7 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
 	auto currentRights = isCreator
 		? MTP_channelAdminRights(MTP_flags(~MTPDchannelAdminRights::Flag::f_add_admins | MTPDchannelAdminRights::Flag::f_add_admins))
 		: notAdmin ? MTP_channelAdminRights(MTP_flags(0)) : it->second;
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	auto box = Box<EditAdminBox>(_channel, user, currentRights);
 	auto canEdit = (_additional.adminCanEdit.find(user) != _additional.adminCanEdit.end());
 	auto canSave = notAdmin ? _channel->canAddAdmins() : canEdit;
@@ -749,7 +749,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
 	auto restrictedRights = (it == _additional.restrictedRights.cend())
 		? MTP_channelBannedRights(MTP_flags(0), MTP_int(0))
 		: it->second;
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	auto hasAdminRights = false;
 	auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, restrictedRights);
 	if (_channel->canBanMembers()) {
@@ -815,10 +815,10 @@ void ParticipantsBoxController::editRestrictedDone(not_null<UserData*> user, con
 
 void ParticipantsBoxController::kickMember(not_null<UserData*> user) {
 	auto text = (_channel->isMegagroup() ? lng_profile_sure_kick : lng_profile_sure_kick_channel)(lt_user, user->firstName);
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	_editBox = Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), [weak, user] {
-		if (weak) {
-			weak->kickMemberSure(user);
+		if (const auto strong = weak.get()) {
+			strong->kickMemberSure(user);
 		}
 	}), LayerOption::KeepOther);
 }
@@ -1255,7 +1255,7 @@ void AddParticipantBoxController::showAdmin(not_null<UserData*> user, bool sure)
 	}
 
 	// Check restrictions.
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	auto alreadyIt = _additional.adminRights.find(user);
 	auto currentRights = (_additional.creator == user)
 		? MTP_channelAdminRights(MTP_flags(~MTPDchannelAdminRights::Flag::f_add_admins | MTPDchannelAdminRights::Flag::f_add_admins))
@@ -1398,7 +1398,7 @@ void AddParticipantBoxController::showRestricted(not_null<UserData*> user, bool
 	}
 
 	// Check restrictions.
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	auto alreadyIt = _additional.restrictedRights.find(user);
 	auto currentRights = MTP_channelBannedRights(MTP_flags(0), MTP_int(0));
 	auto hasAdminRights = false;
@@ -1436,12 +1436,12 @@ void AddParticipantBoxController::showRestricted(not_null<UserData*> user, bool
 }
 
 void AddParticipantBoxController::restrictUserSure(not_null<UserData*> user, const MTPChannelBannedRights &oldRights, const MTPChannelBannedRights &newRights) {
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	MTP::send(MTPchannels_EditBanned(_channel->inputChannel, user->inputUser, newRights), rpcDone([megagroup = _channel.get(), user, weak, oldRights, newRights](const MTPUpdates &result) {
 		Auth().api().applyUpdates(result);
 		megagroup->applyEditBanned(user, oldRights, newRights);
-		if (weak) {
-			weak->editRestrictedDone(user, newRights);
+		if (const auto strong = weak.get()) {
+			strong->editRestrictedDone(user, newRights);
 		}
 	}));
 }
@@ -1477,7 +1477,7 @@ void AddParticipantBoxController::kickUser(not_null<UserData*> user, bool sure)
 	}
 
 	// Check restrictions.
-	auto weak = base::make_weak_unique(this);
+	auto weak = base::make_weak(this);
 	if (_additional.adminRights.find(user) != _additional.adminRights.end() || _additional.creator == user) {
 		// The user is an admin or creator.
 		if (_additional.adminCanEdit.find(user) != _additional.adminCanEdit.end()) {
diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.h b/Telegram/SourceFiles/profile/profile_channel_controllers.h
index 4f3ea6c2a6..56346036cb 100644
--- a/Telegram/SourceFiles/profile/profile_channel_controllers.h
+++ b/Telegram/SourceFiles/profile/profile_channel_controllers.h
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "boxes/peer_list_box.h"
 #include "mtproto/sender.h"
 #include "base/timer.h"
-#include "base/weak_unique_ptr.h"
+#include "base/weak_ptr.h"
 #include "info/profile/info_profile_members_controllers.h"
 
 namespace Window {
@@ -38,7 +38,7 @@ class ParticipantsBoxController
 	: public PeerListController
 	, private base::Subscriber
 	, private MTP::Sender
-	, public base::enable_weak_from_this {
+	, public base::has_weak_ptr {
 public:
 	enum class Role {
 		Profile,
@@ -212,7 +212,7 @@ private:
 };
 
 // Adding an admin, banned or restricted user from channel members with search + contacts search + global search.
-class AddParticipantBoxController : public PeerListController, private base::Subscriber, private MTP::Sender, public base::enable_weak_from_this {
+class AddParticipantBoxController : public PeerListController, private base::Subscriber, private MTP::Sender, public base::has_weak_ptr {
 public:
 	using Role = ParticipantsBoxController::Role;
 	using Additional = ParticipantsBoxController::Additional;
diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt
index 6da517c289..b9ecb3df36 100644
--- a/Telegram/gyp/telegram_sources.txt
+++ b/Telegram/gyp/telegram_sources.txt
@@ -33,7 +33,7 @@
 <(src_loc)/base/value_ordering.h
 <(src_loc)/base/variant.h
 <(src_loc)/base/virtual_method.h
-<(src_loc)/base/weak_unique_ptr.h
+<(src_loc)/base/weak_ptr.h
 <(src_loc)/base/zlib_help.h
 <(src_loc)/boxes/peers/edit_peer_info_box.cpp
 <(src_loc)/boxes/peers/edit_peer_info_box.h