* Diary sample baseline added to compose-samples

* Updated main README table

* README for Diary app updated

* all Android Studio warnings cleared

* Fixed all warnings within Android studio

* Ran ktlint script

* Deleted unused component

* Placeholder for Editor and forced light mode on app due to calendarView

* updated suggested changes in PR #98

* required changes for PR #98

* Row removed, weight adjusted

* ktlint updated

* Hardcoded string updated to use stringResource

* string hardcoded again as there's an issue with pulling data from stringResource

* Theme and other fixes for PR #98

* changes to theme and comment removed

* stringResource issue fixed

* screenshots added

* updated style for text

* project settings gradle file updated
This commit is contained in:
Unmesh 2022-07-15 09:40:57 -07:00 коммит произвёл GitHub
Родитель fb89ef3afe
Коммит f222c72de6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
35 изменённых файлов: 848 добавлений и 1 удалений

1
Diary/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
/build

52
Diary/README.md Normal file
Просмотреть файл

@ -0,0 +1,52 @@
# Diary
This sample is built with Jetpack Compose, the new UI framework in Android.
## Getting Started
To learn how to load apps on the Surface Duo emulator, see the [documentation](https://docs.microsoft.com/dual-screen/android), and follow [the blog](https://devblogs.microsoft.com/surface-duo).
## Features
When the app is in dual mode, both the Calendar View and the Editor will be spread out on two separate screens. If the user is in portrait mode, the app will give you the ability to toggle between calendar view and the editor
The sample uses the [Companion Pane](https://docs.microsoft.com/dual-screen/introduction#companion-pane) app pattern to show a Calendar view + Diary on One Screen , and the diary editor box for the selected day on the other pane.
## Single Screen Mode
In single screen mode, users are able to view one of two screens at a time: Diary Writer or Calendar with Content for the day. A button appears in the Calendar window and the editor that can be used to toggle between the two screens
![Screenshot_20220713-090404](https://user-images.githubusercontent.com/20245964/178855424-a3cdb8dc-b33f-432b-a328-c95de79af11c.png)
![Screenshot_20220713-090516](https://user-images.githubusercontent.com/20245964/178855427-6c498346-3ccb-4fad-8749-ac4993f03728.png)
## Dual Screen Mode
In dual screen mode, both windows are visible, so no buttons are visible to enable toggle.
![Screenshot_20220713-090345](https://user-images.githubusercontent.com/20245964/178855463-b6df48ae-f57d-4529-b0ce-23e32c19edff.png)
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## License
Copyright (c) Microsoft Corporation.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

61
Diary/build.gradle Normal file
Просмотреть файл

@ -0,0 +1,61 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.microsoft.device.display.samples.diary"
minSdk 29
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion composeVersion
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation androidxDependencies.ktxCore
implementation composeDependencies.composeUI
implementation composeDependencies.composeRuntime
implementation composeDependencies.composeMaterial
implementation composeDependencies.composeUITooling
implementation composeDependencies.activityCompose
implementation googleDependencies.systemUiController
implementation microsoftDependencies.twoPaneLayout
}

Просмотреть файл

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.microsoft.device.display.samples.diary">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TwoPaneExample"
tools:targetApi="31">
<activity
android:name="com.microsoft.device.display.samples.diary.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.TwoPaneExample">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Просмотреть файл

@ -0,0 +1,9 @@
** Sample text for the diary App **
Today was wonderful
- I went for a run in the morning at 7:30 AM
- Had some herbal tea at 8:30 AM
- Picked up some breakfast at local bakery in Seattle
- Started working at 9:15 AM
- Had Pizza for Lunch at Cafe 86

Просмотреть файл

@ -0,0 +1,39 @@
package com.microsoft.device.display.samples.diary
import android.content.Context
import android.util.Log
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.IOException
fun readDayFile(fileName: String, rootDir: File, context: Context): String {
val file = File(rootDir, "/$fileName")
if (!file.exists()) {
return context.getString(R.string.no_diary_content)
}
val fileReader = FileReader(file)
val dayContent = BufferedReader(fileReader).useLines { lines ->
val content = StringBuilder()
lines.forEach { content.append(it + System.getProperty("line.separator")) }
content.toString()
}
fileReader.close()
return dayContent
}
/**
* To save a txt file to a specified file path
*/
fun saveFile(fileName: String, content: String, rootDir: File) {
val file = File(rootDir, "/$fileName")
val out = FileWriter(file)
try {
out.write(content)
out.close()
} catch (ioError: IOException) {
Log.d("TAG", "saveFile: IO ERROR -> $ioError")
}
}

Просмотреть файл

@ -0,0 +1,27 @@
package com.microsoft.device.display.samples.diary
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.ui.Modifier
import com.microsoft.device.display.samples.diary.ui.theme.DiaryTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DiaryTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MainApp()
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
package com.microsoft.device.display.samples.diary
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import com.microsoft.device.display.samples.diary.ui.pages.CalendarPage
import com.microsoft.device.display.samples.diary.ui.pages.DiaryPage
import com.microsoft.device.dualscreen.twopanelayout.TwoPaneLayout
import java.io.File
import java.time.LocalDate
/**
* For handling window navigation for Surface Duo, this acts as a main Controller for both the Composable
*/
@Composable
fun MainApp() {
val context = LocalContext.current
val rootDataDir: File = context.applicationContext.dataDir
var text by rememberSaveable { mutableStateOf("") }
var currentSelectedDate by rememberSaveable {
mutableStateOf(LocalDate.now())
}
var content by rememberSaveable { mutableStateOf("") }
val updateDate: (LocalDate) -> Unit = { date ->
currentSelectedDate = date
}
val updateContent: () -> Unit = {
content = readDayFile(currentSelectedDate.toString(), rootDataDir, context)
}
val updateText: (String) -> Unit = { newText ->
text = newText
}
TwoPaneLayout(
pane1 = {
CalendarPage(
content = content,
selectedDate = currentSelectedDate,
updateDate = updateDate,
updateContent = updateContent
)
},
pane2 = {
DiaryPage(
text = text,
updateText = updateText,
selectedDate = currentSelectedDate,
updateContent = updateContent
)
}
)
}

Просмотреть файл

@ -0,0 +1,124 @@
package com.microsoft.device.display.samples.diary.ui.pages
import android.view.ViewGroup
import android.widget.CalendarView
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import com.microsoft.device.display.samples.diary.R
import com.microsoft.device.dualscreen.twopanelayout.TwoPaneScope
import java.time.LocalDate
/**
* The CalendarView Composable which also contains the Diary Content for the selected day
*/
@Composable
fun TwoPaneScope.CalendarPage(
content: String,
selectedDate: LocalDate,
updateDate: (LocalDate) -> Unit,
updateContent: () -> Unit
) {
val twoPaneScope = this
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = stringResource(id = R.string.app_name))
},
backgroundColor = MaterialTheme.colors.primaryVariant,
actions = {
if (twoPaneScope.isSinglePane) {
IconButton(
onClick = { twoPaneScope.navigateToPane2() }
) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(R.string.edit_diary)
)
}
}
}
)
}
) {
Column {
AndroidView(
{
CalendarView(it)
.apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
},
modifier = Modifier.wrapContentWidth(),
update = {
it.setOnDateChangeListener { _, year, month, dayOfMonth ->
val currentSelectedDate = LocalDate.of(year, month + 1, dayOfMonth)
updateDate(currentSelectedDate)
updateContent()
}
}
)
Spacer(
modifier = Modifier
.background(color = Color.Gray)
.height(1.dp)
.fillMaxWidth()
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
text = selectedDate.toString(),
style = TextStyle(
fontSize = 24.sp,
textAlign = TextAlign.Center,
shadow = Shadow(
color = Color.Gray,
offset = Offset(4.0f, 5.0f),
blurRadius = 2f
)
)
)
Text(
text = content,
Modifier.padding(10.dp),
style = TextStyle(
fontSize = 18.sp,
textAlign = TextAlign.Left,
)
)
}
}
}

Просмотреть файл

@ -0,0 +1,92 @@
package com.microsoft.device.display.samples.diary.ui.pages
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DateRange
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.microsoft.device.display.samples.diary.R
import com.microsoft.device.display.samples.diary.saveFile
import com.microsoft.device.dualscreen.twopanelayout.TwoPaneScope
import java.io.File
import java.time.LocalDate
/**
* EditorPage Composable contains the Editor for the Diary for selected date on the CalendarView
*/
@Composable
fun TwoPaneScope.DiaryPage(
text: String,
updateText: (String) -> Unit,
selectedDate: LocalDate,
updateContent: () -> Unit
) {
val twoPaneScope = this
val context = LocalContext.current
val rootDataDir: File = context.applicationContext.dataDir
Scaffold(
topBar = {
TopAppBar(
title = {
if (isSinglePane) {
Text(text = stringResource(R.string.app_name))
}
},
backgroundColor = MaterialTheme.colors.primaryVariant,
actions = {
if (twoPaneScope.isSinglePane) {
IconButton(
onClick = { twoPaneScope.navigateToPane1() }
) {
Icon(
imageVector = Icons.Default.DateRange,
contentDescription = stringResource(R.string.date_picker)
)
}
}
}
)
}
) {
Column {
TextField(
value = text,
placeholder = { Text(stringResource(R.string.diary_placeholder)) },
textStyle = MaterialTheme.typography.h5,
onValueChange = { newText -> updateText(newText) },
modifier = Modifier
.fillMaxSize()
.weight(0.9f)
)
Button(
modifier = Modifier
.width(150.dp)
.padding(all = 10.dp)
.weight(0.1f),
onClick = {
saveFile(selectedDate.toString(), text, rootDataDir)
updateContent()
}
) {
Text(text = stringResource(R.string.save_button))
}
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
package com.microsoft.device.display.samples.diary.ui.theme
import androidx.compose.ui.graphics.Color
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
val Teal500 = Color(0xFF03CAC5)

Просмотреть файл

@ -0,0 +1,11 @@
package com.microsoft.device.display.samples.diary.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)

Просмотреть файл

@ -0,0 +1,25 @@
package com.microsoft.device.display.samples.diary.ui.theme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)
@Composable
fun DiaryTheme(
content: @Composable () -> Unit
) {
val colors = LightColorPalette
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}

Просмотреть файл

@ -0,0 +1,33 @@
package com.microsoft.device.display.samples.diary.ui.theme
import androidx.compose.material.Typography
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 24.sp,
textAlign = TextAlign.Center,
shadow = Shadow(
color = Color.Gray,
offset = Offset(4.0f, 5.0f),
blurRadius = 2f
)
),
body2 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
textAlign = TextAlign.Left
)
)

Просмотреть файл

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

Просмотреть файл

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

Просмотреть файл

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Просмотреть файл

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Двоичные данные
Diary/src/main/res/mipmap-hdpi/ic_launcher.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
Diary/src/main/res/mipmap-hdpi/ic_launcher_round.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.8 KiB

Двоичные данные
Diary/src/main/res/mipmap-mdpi/ic_launcher.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 982 B

Двоичные данные
Diary/src/main/res/mipmap-mdpi/ic_launcher_round.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Двоичные данные
Diary/src/main/res/mipmap-xhdpi/ic_launcher.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.9 KiB

Двоичные данные
Diary/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.8 KiB

Двоичные данные
Diary/src/main/res/mipmap-xxhdpi/ic_launcher.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.8 KiB

Двоичные данные
Diary/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.8 KiB

Двоичные данные
Diary/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.8 KiB

Двоичные данные
Diary/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.6 KiB

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

Просмотреть файл

@ -0,0 +1,10 @@
<resources>
<string name="app_name">Compose Diary</string>
<string name="calendar_button">Calendar</string>
<string name="diary_editor">Diary Editor</string>
<string name="save_button">Save Diary</string>
<string name="diary_placeholder">Start writing...</string>
<string name="no_diary_content">No data available for the day</string>
<string name="edit_diary">Edit Diary</string>
<string name="date_picker">Date Selector</string>
</resources>

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.TwoPaneExample" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/purple_700</item>
</style>
</resources>

Просмотреть файл

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

Просмотреть файл

@ -63,6 +63,8 @@ The samples are built with Microsoft Compose libraries, [TwoPaneLayout](https://
| | |
| [DragAndDrop](https://github.com/microsoft/surface-duo-compose-samples/tree/main/DragAndDrop) | ![DragAndDrop app icon](screenshots/drag_and_drop.svg) | Drag and Drop sample that shows how to implement drag and drop in your Android app, following the Android [drag and drop guidance](https://developer.android.com/guide/topics/ui/drag-drop) in Jetpack Compose. |
| | |
| [Diary](https://github.com/microsoft/surface-duo-compose-samples/tree/main/Diary) | |Diary app sample that encorporates Calendar view on one pane and diary editor for the selected date on the other pane, following the Android [Companion Pane](https://docs.microsoft.com/dual-screen/introduction#companion-pane) app pattern. |
| | |
## Social links

Просмотреть файл

@ -5,4 +5,4 @@
rootProject.name = "ComposeSamples"
include ':ListDetail', ':CompanionPane', ':DualView', ':ExtendedCanvas', ':ComposeGallery',
':TwoPage', ':NavigationRail', ':DyAdd', ':DragAndDrop', ':VideoPlusChat', ':SourceEditorCompose'
':TwoPage', ':NavigationRail', ':DyAdd', ':DragAndDrop', ':VideoPlusChat', ':SourceEditorCompose', ':Diary'