<commit_before><!--
  - @copyright Copyright (c) 2019 <NAME> <<EMAIL>>
  -
  - @author <NAME> <<EMAIL>>
  -
  - @license GNU AGPL version 3 or any later version
  -
  - This program is free software: you can redistribute it and/or modify
  - it under the terms of the GNU Affero General Public License as
  - published by the Free Software Foundation, either version 3 of the
  - License, or (at your option) any later version.
  -
  - This program 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 Affero General Public License for more details.
  -
  - You should have received a copy of the GNU Affero General Public License
  - along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<template>
	<AppNavigation class="vue navigation">
		<AppNavigationSearch
			v-model="searchText"
			@input="debounceFetchSearchResults" />
		<ul>
			<Caption v-if="isSearching"
				:title="t('spreed', 'Conversations')" />

			<ConversationsList
				:search-text="searchText" />

			<template v-if="isSearching">
				<Caption
					:title="t('spreed', 'Contacts')" />
				<ContactsList v-if="searchResultsUsers.length !== 0" :contacts="searchResultsUsers" />
				<Hint v-else-if="contactsLoading" :hint="t('spreed', 'Loading')" />
				<Hint v-else :hint="t('spreed', 'No search results')" />

				<Caption
					:title="t('spreed', 'Groups')" />
				<GroupsList v-if="searchResultsGroups.length !== 0" :groups="searchResultsGroups" />
				<Hint v-else-if="contactsLoading" :hint="t('spreed', 'Loading')" />
				<Hint v-else :hint="t('spreed', 'No search results')" />

				<Caption
					:title="t('spreed', 'New conversation')" />
				<NewPublicConversation
					:search-text="searchText" />
				<NewPrivateConversation
					:search-text="searchText" />
			</template>
		</ul>
	</AppNavigation>
</template>

<script>
import AppNavigation from 'nextcloud-vue/dist/Components/AppNavigation'
import AppNavigationSearch from './AppNavigationSearch/AppNavigationSearch'
import Caption from './Caption/Caption'
import ContactsList from './ContactsList/ContactsList'
import ConversationsList from './ConversationsList/ConversationsList'
import GroupsList from './GroupsList/GroupsList'
import Hint from './Hint/Hint'
import NewPrivateConversation from './NewConversation/NewPrivateConversation'
import NewPublicConversation from './NewConversation/NewPublicConversation'
import debounce from 'debounce'
import { EventBus } from '../../services/EventBus'
import { searchPossibleConversations } from '../../services/conversationsService'
import { getCurrentUser } from '@nextcloud/auth'
import { CONVERSATION } from '../../constants'

export default {

	name: 'Navigation',

	components: {
		AppNavigation,
		AppNavigationSearch,
		Caption,
		ContactsList,
		ConversationsList,
		GroupsList,
		Hint,
		NewPrivateConversation,
		NewPublicConversation,
	},

	data() {
		return {
			searchText: '',
			searchResults: {},
			searchResultsUsers: [],
			searchResultsGroups: [],
			contactsLoading: false,
		}
	},

	computed: {
		conversationsList() {
			return this.$store.getters.conversationsList
		},
		isSearching() {
			return this.searchText !== ''
		},
	},

	beforeMount() {
		/**
		 * After a conversation was created, the search filter is reset
		 */
		EventBus.$once('resetSearchFilter', () => {
			this.searchText = ''
		})
	},

	methods: {
		debounceFetchSearchResults: debounce(function() {
			if (this.isSearching) {
				this.fetchSearchResults()
			}
		}, 250),

		async fetchSearchResults() {
			this.contactsLoading = true
			const response = await searchPossibleConversations(this.searchText)
			this.searchResults = response.data.ocs.data
			this.searchResultsUsers = this.searchResults.filter((match) => match.source === 'users' && match.id !== getCurrentUser().uid && !this.hasOneToOneConversationWith(match.id))
			this.searchResultsGroups = this.searchResults.filter((match) => match.source === 'groups')
			this.contactsLoading = false
		},

		hasOneToOneConversationWith(userId) {
			return !!this.conversationsList.find(conversation => conversation.type === CONVERSATION.TYPE.ONE_TO_ONE && conversation.name === userId)
		},
	},
}
</script>

<style lang="scss" scoped>

.navigation {
	width: 300px;
	position: fixed;
	top: 50px;
	left: 0;
	z-index: 500;
	overflow-y: auto;
	overflow-x: hidden;
	// Do not use vh because of mobile headers
	// are included in the calculation
	height: calc(100% - 50px);
	box-sizing: border-box;
	background-color: var(--color-main-background);
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	border-right: 1px solid var(--color-border);
	display: flex;
	flex-direction: column;
	flex-grow: 0;
	flex-shrink: 0;
}

.settings {
	position: sticky;
	bottom: 0;
	border-top: 1px solid lightgray;
}
</style>
<commit_msg>Use variables<commit_after><!--
  - @copyright Copyright (c) 2019 <NAME> <<EMAIL>>
  -
  - @author <NAME> <<EMAIL>>
  -
  - @license GNU AGPL version 3 or any later version
  -
  - This program is free software: you can redistribute it and/or modify
  - it under the terms of the GNU Affero General Public License as
  - published by the Free Software Foundation, either version 3 of the
  - License, or (at your option) any later version.
  -
  - This program 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 Affero General Public License for more details.
  -
  - You should have received a copy of the GNU Affero General Public License
  - along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<template>
	<AppNavigation class="vue navigation">
		<AppNavigationSearch
			v-model="searchText"
			@input="debounceFetchSearchResults" />
		<ul>
			<Caption v-if="isSearching"
				:title="t('spreed', 'Conversations')" />

			<ConversationsList
				:search-text="searchText" />

			<template v-if="isSearching">
				<Caption
					:title="t('spreed', 'Contacts')" />
				<ContactsList v-if="searchResultsUsers.length !== 0" :contacts="searchResultsUsers" />
				<Hint v-else-if="contactsLoading" :hint="t('spreed', 'Loading')" />
				<Hint v-else :hint="t('spreed', 'No search results')" />

				<Caption
					:title="t('spreed', 'Groups')" />
				<GroupsList v-if="searchResultsGroups.length !== 0" :groups="searchResultsGroups" />
				<Hint v-else-if="contactsLoading" :hint="t('spreed', 'Loading')" />
				<Hint v-else :hint="t('spreed', 'No search results')" />

				<Caption
					:title="t('spreed', 'New conversation')" />
				<NewPublicConversation
					:search-text="searchText" />
				<NewPrivateConversation
					:search-text="searchText" />
			</template>
		</ul>
	</AppNavigation>
</template>

<script>
import AppNavigation from 'nextcloud-vue/dist/Components/AppNavigation'
import AppNavigationSearch from './AppNavigationSearch/AppNavigationSearch'
import Caption from './Caption/Caption'
import ContactsList from './ContactsList/ContactsList'
import ConversationsList from './ConversationsList/ConversationsList'
import GroupsList from './GroupsList/GroupsList'
import Hint from './Hint/Hint'
import NewPrivateConversation from './NewConversation/NewPrivateConversation'
import NewPublicConversation from './NewConversation/NewPublicConversation'
import debounce from 'debounce'
import { EventBus } from '../../services/EventBus'
import { searchPossibleConversations } from '../../services/conversationsService'
import { getCurrentUser } from '@nextcloud/auth'
import { CONVERSATION } from '../../constants'

export default {

	name: 'Navigation',

	components: {
		AppNavigation,
		AppNavigationSearch,
		Caption,
		ContactsList,
		ConversationsList,
		GroupsList,
		Hint,
		NewPrivateConversation,
		NewPublicConversation,
	},

	data() {
		return {
			searchText: '',
			searchResults: {},
			searchResultsUsers: [],
			searchResultsGroups: [],
			contactsLoading: false,
		}
	},

	computed: {
		conversationsList() {
			return this.$store.getters.conversationsList
		},
		isSearching() {
			return this.searchText !== ''
		},
	},

	beforeMount() {
		/**
		 * After a conversation was created, the search filter is reset
		 */
		EventBus.$once('resetSearchFilter', () => {
			this.searchText = ''
		})
	},

	methods: {
		debounceFetchSearchResults: debounce(function() {
			if (this.isSearching) {
				this.fetchSearchResults()
			}
		}, 250),

		async fetchSearchResults() {
			this.contactsLoading = true
			const response = await searchPossibleConversations(this.searchText)
			this.searchResults = response.data.ocs.data
			this.searchResultsUsers = this.searchResults.filter((match) => match.source === 'users' && match.id !== getCurrentUser().uid && !this.hasOneToOneConversationWith(match.id))
			this.searchResultsGroups = this.searchResults.filter((match) => match.source === 'groups')
			this.contactsLoading = false
		},

		hasOneToOneConversationWith(userId) {
			return !!this.conversationsList.find(conversation => conversation.type === CONVERSATION.TYPE.ONE_TO_ONE && conversation.name === userId)
		},
	},
}
</script>

<style lang="scss" scoped>

@import '../../assets/variables';

.navigation {
	width: $navigation-width;
	position: fixed;
	top: 50px;
	left: 0;
	z-index: 500;
	overflow-y: auto;
	overflow-x: hidden;
	// Do not use vh because of mobile headers
	// are included in the calculation
	height: calc(100% - 50px);
	box-sizing: border-box;
	background-color: var(--color-main-background);
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	border-right: 1px solid var(--color-border);
	display: flex;
	flex-direction: column;
	flex-grow: 0;
	flex-shrink: 0;
}

.settings {
	position: sticky;
	bottom: 0;
	border-top: 1px solid var(--color-border-dark);
}
</style>

{'fraction_non_alphanumeric': 0.13957455348183825, 'fraction_numerical': 0.005719446116797111, 'mean_word_length': 4.011060834590246, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4639839', 'n_tokens_mistral': 3462, 'n_tokens_neox': 3091, 'n_words': 779}