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

fix: search filter private views #5646

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:appflowy_backend/protobuf/flowy-search/notification.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:protobuf/protobuf.dart';

part 'command_palette_bloc.freezed.dart';

Expand Down Expand Up @@ -90,7 +91,8 @@ class CommandPaletteBloc

_messagesReceived++;

final searchResults = _filterDuplicates(results.items);
final allItems = [...state.results, ...results.items];
final searchResults = _removeDuplicates(allItems);
searchResults.sort((a, b) => b.score.compareTo(a.score));

emit(
Expand Down Expand Up @@ -133,29 +135,30 @@ class CommandPaletteBloc
);
}

List<SearchResultPB> _filterDuplicates(List<SearchResultPB> results) {
final currentItems = [...state.results];
final res = [...results];
/// Remove duplicates, where retained item is the one with the highest score.
List<SearchResultPB> _removeDuplicates(List<SearchResultPB> items) {
final res = <SearchResultPB>[];

for (final item in results) {
if (item.data.trim().isEmpty) {
continue;
}

final duplicateIndex = currentItems.indexWhere((a) => a.id == item.id);
for (final item in items) {
final duplicateIndex = res.indexWhere((a) => a.id == item.id);
if (duplicateIndex == -1) {
res.add(item);
continue;
}

final duplicate = currentItems[duplicateIndex];
if (item.score < duplicate.score) {
res.remove(item);
} else {
currentItems.remove(duplicate);
var (keep, discard) = item.score > res[duplicateIndex].score
? (item, res[duplicateIndex])
: (res[duplicateIndex], item);

if (keep.preview.isEmpty && discard.preview.isNotEmpty) {
keep.freeze();
keep = keep.rebuild((i) => i.preview = discard.preview);
}

res[duplicateIndex] = keep;
}

return res..addAll(currentItems);
return res;
}

void _performSearch(String value) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ class RecentViewTile extends StatelessWidget {
children: [
icon,
const HSpace(6),
FlowyText(view.name),
Flexible(
child: FlowyText(
view.name,
overflow: TextOverflow.ellipsis,
),
),
],
),
focusColor: Theme.of(context).colorScheme.primary.withOpacity(0.1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class _SearchResultTileState extends State<SearchResultTile> {
style: HoverStyle(
hoverColor: Theme.of(context).colorScheme.primary.withOpacity(0.1),
foregroundColorOnHover: AFThemeExtension.of(context).textColor,
borderRadius: BorderRadius.zero,
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:flutter/material.dart';

import 'package:appflowy/startup/startup.dart';
Expand All @@ -15,6 +14,7 @@ import 'package:appflowy/workspace/presentation/settings/widgets/feature_flags/f
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_page.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_notifications_view.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Expand All @@ -41,15 +41,16 @@ class SettingsDialog extends StatelessWidget {
child: BlocBuilder<SettingsDialogBloc, SettingsDialogState>(
builder: (context, state) => FlowyDialog(
width: MediaQuery.of(context).size.width * 0.7,
constraints: const BoxConstraints(maxWidth: 784, minWidth: 564),
constraints: const BoxConstraints(maxWidth: 894, minWidth: 674),
heightFactor: 0.8,
child: ScaffoldMessenger(
child: Scaffold(
backgroundColor: Colors.transparent,
body: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 200,
width: 230,
child: SettingsMenu(
userProfile: user,
changeSelectedPage: (index) => context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class FlowyDialog extends StatelessWidget {
this.alignment,
this.insetPadding,
this.width,
this.heightFactor = 0.7,
});

final Widget? title;
Expand All @@ -39,10 +40,12 @@ class FlowyDialog extends StatelessWidget {

final double? width;

final double heightFactor;

@override
Widget build(BuildContext context) {
final windowSize = MediaQuery.of(context).size;
final size = windowSize * 0.7;
final size = windowSize * heightFactor;

return SimpleDialog(
alignment: alignment,
Expand Down
10 changes: 8 additions & 2 deletions frontend/rust-lib/flowy-core/src/deps_resolve/search_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ impl SearchDepsResolver {
folder_manager: Arc<FolderManager>,
) -> Arc<SearchManager> {
let folder_handler = Arc::new(FolderSearchHandler::new(folder_indexer));
let document_handler = Arc::new(DocumentSearchHandler::new(cloud_service, folder_manager));
Arc::new(SearchManager::new(vec![folder_handler, document_handler]))
let document_handler = Arc::new(DocumentSearchHandler::new(
cloud_service,
folder_manager.clone(),
));
Arc::new(SearchManager::new(
folder_manager,
vec![folder_handler, document_handler],
))
}
}
2 changes: 1 addition & 1 deletion frontend/rust-lib/flowy-folder/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@ impl FolderManager {
}

/// Filter the views that are in the trash and belong to the other private sections.
fn get_view_ids_should_be_filtered(&self, folder: &Folder) -> Vec<String> {
pub fn get_view_ids_should_be_filtered(&self, folder: &Folder) -> Vec<String> {
let trash_ids = self.get_all_trash_ids(folder);
let other_private_view_ids = self.get_other_private_view_ids(folder);
[trash_ids, other_private_view_ids].concat()
Expand Down
5 changes: 5 additions & 0 deletions frontend/rust-lib/flowy-search/src/folder/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ impl IndexManager for FolderIndexManagerImpl {

let (icon, icon_ty) = self.extract_icon(data.icon, data.layout);

let delete_term = Term::from_field_text(id_field, &data.id.clone());
// Remove old index just in case we have duplicate messages
// from the index content receiver.
index_writer.delete_term(delete_term);

// Add new index
let _ = index_writer.add_document(doc![
id_field => data.id,
Expand Down
37 changes: 35 additions & 2 deletions frontend/rust-lib/flowy-search/src/services/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::sync::Arc;
use super::notifier::{SearchNotifier, SearchResultChanged, SearchResultReceiverRunner};
use crate::entities::{SearchFilterPB, SearchResultNotificationPB, SearchResultPB};
use flowy_error::FlowyResult;
use flowy_folder::manager::FolderManager;
use lib_dispatch::prelude::af_spawn;
use lib_infra::async_trait::async_trait;
use tokio::sync::broadcast;
Expand Down Expand Up @@ -35,12 +36,13 @@ pub trait SearchHandler: Send + Sync + 'static {
/// to the client until the query has been fully completed.
///
pub struct SearchManager {
pub folder_manager: Arc<FolderManager>,
pub handlers: HashMap<SearchType, Arc<dyn SearchHandler>>,
notifier: SearchNotifier,
}

impl SearchManager {
pub fn new(handlers: Vec<Arc<dyn SearchHandler>>) -> Self {
pub fn new(folder_manager: Arc<FolderManager>, handlers: Vec<Arc<dyn SearchHandler>>) -> Self {
let handlers: HashMap<SearchType, Arc<dyn SearchHandler>> = handlers
.into_iter()
.map(|handler| (handler.search_type(), handler))
Expand All @@ -50,7 +52,11 @@ impl SearchManager {
let (notifier, _) = broadcast::channel(100);
af_spawn(SearchResultReceiverRunner(Some(notifier.subscribe())).run());

Self { handlers, notifier }
Self {
folder_manager,
handlers,
notifier,
}
}

pub fn get_handler(&self, search_type: SearchType) -> Option<&Arc<dyn SearchHandler>> {
Expand All @@ -63,19 +69,46 @@ impl SearchManager {
filter: Option<SearchFilterPB>,
channel: Option<String>,
) {
let mutex_folder = self.folder_manager.get_mutex_folder();
let guard = mutex_folder.read();
let folder = match guard.as_ref() {
Some(folder) => folder,
None => {
let notification = SearchResultNotificationPB {
items: vec![],
sends: 0 as u64,
channel,
query,
};
let _ = self
.notifier
.send(SearchResultChanged::SearchResultUpdate(notification));
return;
},
};
let private_views = self.folder_manager.get_view_ids_should_be_filtered(folder);
tracing::warn!("Private views: {:?}", private_views);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to self to remove this


let max: usize = self.handlers.len();
let handlers = self.handlers.clone();
for (_, handler) in handlers {
let q = query.clone();
let f = filter.clone();
let ch = channel.clone();
let notifier = self.notifier.clone();
let private_view_ids = private_views.clone();

af_spawn(async move {
let res = handler.perform_search(q.clone(), f).await;

let items = res.unwrap_or_default();

// Filter out any items which ID exists in private_views
let items = items
.into_iter()
.filter(|item| !private_view_ids.contains(&item.id))
.collect();

let notification = SearchResultNotificationPB {
items,
sends: max as u64,
Expand Down
Loading