package com.ubisam.ubgitea import android.content.ActivityNotFoundException import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.runtime.saveable.rememberSaveable import com.ubisam.ubgitea.domain.model.RepositoryRef import com.ubisam.ubgitea.feature.codebrowser.CodeBrowserScreen import com.ubisam.ubgitea.feature.codebrowser.CodeBrowserTarget import com.ubisam.ubgitea.feature.codebrowser.CodeBrowserUiState import com.ubisam.ubgitea.feature.codebrowser.CodeBrowserViewModel import com.ubisam.ubgitea.feature.codebrowser.CodeReferenceKind import com.ubisam.ubgitea.feature.history.HistoryScreen import com.ubisam.ubgitea.feature.history.HistoryTarget import com.ubisam.ubgitea.feature.history.HistoryUiState import com.ubisam.ubgitea.feature.history.HistoryViewModel import com.ubisam.ubgitea.feature.repositories.ReferenceKind import com.ubisam.ubgitea.feature.repositories.RepositoryListScreen import com.ubisam.ubgitea.feature.repositories.RepositoryListViewModel import com.ubisam.ubgitea.feature.workitems.WorkItemsScreen import com.ubisam.ubgitea.feature.workitems.WorkItemsTarget import com.ubisam.ubgitea.feature.workitems.WorkItemsUiState import com.ubisam.ubgitea.feature.workitems.WorkItemsViewModel import com.ubisam.ubgitea.ui.theme.UBGiteaTheme class MainActivity : ComponentActivity() { private val viewModel: RepositoryListViewModel by viewModels { RepositoryListViewModel.Factory(application) } private val codeBrowserViewModel: CodeBrowserViewModel by viewModels { CodeBrowserViewModel.Factory(application) } private val historyViewModel: HistoryViewModel by viewModels { HistoryViewModel.Factory(application) } private val workItemsViewModel: WorkItemsViewModel by viewModels { WorkItemsViewModel.Factory(application) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { val state by viewModel.state.collectAsState() val codeBrowserState by codeBrowserViewModel.state.collectAsState() val historyState by historyViewModel.state.collectAsState() val workItemsState by workItemsViewModel.state.collectAsState() var browsingCode by rememberSaveable { mutableStateOf(codeBrowserState !is CodeBrowserUiState.Idle) } var browsingHistory by rememberSaveable { mutableStateOf(historyState !is HistoryUiState.Idle) } var browsingWorkItems by rememberSaveable { mutableStateOf(workItemsState !is WorkItemsUiState.Idle) } UBGiteaTheme { if (browsingWorkItems) { WorkItemsScreen( state = workItemsState, onShowIssues = workItemsViewModel::showIssues, onShowPullRequests = workItemsViewModel::showPullRequests, onIssueSelected = workItemsViewModel::openIssue, onPullRequestSelected = workItemsViewModel::openPullRequest, onNextPage = workItemsViewModel::nextPage, onPreviousPage = workItemsViewModel::previousPage, onRetryList = workItemsViewModel::retryList, onRetryDetail = workItemsViewModel::retryDetail, onBackToList = workItemsViewModel::backToList, onBack = { workItemsViewModel.close() browsingWorkItems = false }, onAuthenticationExpired = { workItemsViewModel.close() browsingWorkItems = false viewModel.logout() }, ) } else if (browsingHistory) { HistoryScreen( state = historyState, onCommitSelected = historyViewModel::openCommit, onNextPage = historyViewModel::nextPage, onPreviousPage = historyViewModel::previousPage, onRetryList = historyViewModel::retryList, onRetryDetail = historyViewModel::retryDetail, onRetryPatch = historyViewModel::retryPatch, onBackToList = historyViewModel::backToList, onBack = { historyViewModel.close() browsingHistory = false }, onCompare = historyViewModel::compareAgainstCurrentRef, onCompareNextPage = historyViewModel::compareNextPage, onComparePreviousPage = historyViewModel::comparePreviousPage, onRetryCompare = historyViewModel::retryCompare, onLoadComparePatch = historyViewModel::loadComparePatch, onAuthenticationExpired = { historyViewModel.close() codeBrowserViewModel.close() browsingHistory = false browsingCode = false viewModel.logout() }, ) } else if (browsingCode) { CodeBrowserScreen( state = codeBrowserState, onEntrySelected = codeBrowserViewModel::openEntry, onBreadcrumbSelected = codeBrowserViewModel::openBreadcrumb, onRetry = codeBrowserViewModel::retry, onBack = { if (!codeBrowserViewModel.navigateUp()) { codeBrowserViewModel.close() browsingCode = false } }, onAuthenticationExpired = { codeBrowserViewModel.close() browsingCode = false viewModel.logout() }, onViewHistory = { target -> historyViewModel.open(HistoryTarget(target.repository, target.ref)) browsingHistory = true }, ) } else { RepositoryListScreen( state = state, onSignIn = viewModel::signIn, onCancelSignIn = viewModel::cancelSignIn, onRetry = viewModel::retry, onLogout = viewModel::logout, onRepositorySelected = viewModel::selectRepository, onReferenceSelected = { repository, name, kind -> viewModel.selectReference(name, kind) codeBrowserViewModel.open( CodeBrowserTarget( repository = repository.coordinates, ref = RepositoryRef.of(name), kind = if (kind == ReferenceKind.BRANCH) { CodeReferenceKind.BRANCH } else { CodeReferenceKind.TAG }, ), ) browsingCode = true }, onReferencesRefresh = viewModel::refreshReferences, onBackToRepositories = viewModel::backToRepositories, onNextPage = viewModel::nextPage, onPreviousPage = viewModel::previousPage, onRefreshRepositories = viewModel::refreshRepositories, onRetryLastPushedBranch = viewModel::retryRowLastPushedBranch, onShowAllRepositories = viewModel::showAllRepositories, onShowFavorites = viewModel::showFavorites, onToggleFavorite = viewModel::toggleFavorite, onViewWorkItems = { repository -> workItemsViewModel.open(WorkItemsTarget(repository.coordinates)) browsingWorkItems = true }, ) } LaunchedEffect(viewModel) { viewModel.browserRequests.collect(::openSystemBrowser) } } } consumeCallback(intent) } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) setIntent(intent) consumeCallback(intent) } private fun openSystemBrowser(uri: String) { try { startActivity( Intent(Intent.ACTION_VIEW, Uri.parse(uri)).apply { addCategory(Intent.CATEGORY_BROWSABLE) }, ) } catch (_: ActivityNotFoundException) { viewModel.browserLaunchFailed() } } private fun consumeCallback(intent: Intent?) { val callback = intent?.dataString ?: return setIntent(Intent(intent).setData(null)) viewModel.handleCallback(callback) } }