gpt4 book ai didi

firebase - 如何映射用户特定的喜欢/收藏夹?类似于大多数社交应用程序上的点赞功能

转载 作者:行者123 更新时间:2023-12-04 03:42:27 27 4
gpt4 key购买 nike

您好,我是一名自学 Flutter 的开发人员,正在编写我的第一个应用程序。我正在 Flutter 中构建一个基本的报价应用程序,它使用 Firebase 进行身份验证,使用 FireStore 作为数据库。这是 FireStore noSQL 架构:

有一个故事集合,它是只读数据,提供图像链接和文本,如下所示。请注意,文档 ID 是在故事集合中自动生成的:

Stories Collection

然后是一个 Users 集合,用于存储用户数据,例如用户名、电子邮件、帐户创建日期时间和喜欢数组 [可能存储喜欢的故事]。在此集合中,文档的 ID 是经过身份验证(登录)的用户的 UID(唯一 ID)。

User's collection

下面是我正在追寻的用户故事以及我的方法:

每当用户点击下面最喜欢的图标时,必须将赞保存到用户集合中,其中用户的 uid 是文档 ID,并将喜欢的故事存储在 likes 数组中。

Simulator Screenshot of UI before like

然后使用 if 语句说,如果经过身份验证的用户在 likes 数组中有故事,则将轮廓上的白色心形变成红色心形,如下所示:

Simulator Screenshot of UI after like

但是,我的代码中存在一个错误,当用户点击最喜欢的图标时,所有故事的红心都会立即变红。有人可以帮忙吗?这是代码片段:

class FirestoreSlideshowState extends State<FirestoreSlideshow> {
static const likedKey = 'liked_key';

bool liked;

final PageController ctrl = PageController(viewportFraction: 0.8);

final Firestore db = Firestore.instance;
Stream slides;

String activeTag = 'favs';

// Keep track of current page to avoid unnecessary renders

int currentPage = 0;


@override

void initState() {

super.initState();
_restorePersistedPreference();
_queryDb();

// Set state when page changes
ctrl.addListener(() {
int next = ctrl.page.round();

if (currentPage != next) {
setState(() {
currentPage = next;
});
}
});
}

void _restorePersistedPreference() async {
var preferences = await SharedPreferences.getInstance();
var liked = preferences.getBool(likedKey) ?? false;
setState(() {
this.liked = liked;
});
}

void _persistPreference() async {
setState(() {
liked = !liked;
});
var preferences = await SharedPreferences.getInstance();
preferences.setBool(likedKey, liked);
}

@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: slides,
initialData: [],
builder: (context, AsyncSnapshot snap) {
List slideList = snap.data.toList();

return PageView.builder(
controller: ctrl,
itemCount: slideList.length,
itemBuilder: (context, int currentIdx) {
if (slideList.length >= currentIdx) {
// Active page
bool active = currentIdx == currentPage;
return _buildStoryPage(slideList[currentIdx], active);
}
});
});
}

Stream _queryDb({String tag = 'favs'}) {
// Make a Query
Query query = db.collection('Stories').where('tags', arrayContains: tag);

// Map the documents to the data payload
slides =
query.snapshots().map((list) => list.documents.map((doc) => doc.data));

// Update the active tag
setState(() {
activeTag = tag;
});
}

_buildStoryPage(Map data, bool active) {

final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
// Animated Properties
final double blur = active ? 20 : 0;
final double offset = active ? 20 : 0;
final double top = active ? 75 : 150;

return AnimatedContainer(
duration: Duration(milliseconds: 500),
curve: Curves.easeOutQuint,
width: _width / 2,
height: _height,
margin: EdgeInsets.only(top: top, bottom: 20, right: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(data['img']),
),
boxShadow: [
BoxShadow(
color: Colors.black87,
blurRadius: blur,
offset: Offset(offset, offset))
]),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(data['quote'],
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontFamily: "Typewriter")),
),
),
SizedBox(height: 20),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(data['author'],
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontFamily: "Typewriter")),
),
SizedBox(height: 20),
Row(mainAxisAlignment: MainAxisAlignment.end, children: [

IconButton(
icon: Icon(liked ? Icons.favorite : Icons.favorite_border,
color: liked ? Colors.red : Colors.grey[50]),
onPressed: (){



_persistPreference();


} ),


IconButton(
icon: Icon(
Icons.share,
color: Colors.white,
),
onPressed: () {
share();
})
])
],
));
}
}


最佳答案

我建议为喜欢的人制作另一个收藏。如果此应用程序要扩展,由于 Firestore 文档的大小限制为 1 MB,您将限制用户的报价数量。所以这是一个建议的解决方案:

/likes/{likeId}的文档结构

{
'userId': string
'quoteId': string
}

然后,如果您想加载喜欢的名言列表,您可以执行如下查询:

_db.collection(likes).where('userId', isEqualTo: currentUserId).get()

然后您可以从那里根据上面的结构从 likes 对象中包含的引用 ID 加载引用。为避免无故加载大量文档,您还可以实现 pagination在您的查询中。

所以现在当有人想要引用时,您可以在 likes 集合中创建一个新的 like 对象,其中包含引用 ID 和用户 ID,如上所示。

要删除/取消点赞,您需要找到同时匹配 userId 和 quoteId 的文档才能将其删除

var snap = _db.collection(likes).where('userId', isEqualTo: currentUserId).where('quoteId', isEqualTo: quoteId).get();
if(snap.docs != null && snap.docs.isNotEmpty){
//the record exists
snap.docs.first.ref.delete() // this will delete the first record in the database that matches this like. Ideally there will only ever be one (you should check to make sure a document doesn't already exist before creating a new one)
}

在 flutter 方面,您可能会有一个显示这些列表的 ListView。我建议制作一个组件,使用 future builder 从 id 加载报价。

如果您需要更多 Flutter 端代码示例,请告诉我。祝你好运!

关于firebase - 如何映射用户特定的喜欢/收藏夹?类似于大多数社交应用程序上的点赞功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65732310/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com