Repository: obsidian-tasks-group/obsidian-tasks (ts)

Issue:
Cannot adjust scheduled date when automatically set via plugin option, if editing via the Pencil icon
### Please check that this issue has NOT been reported before.

- [X] I searched previous [Bug Reports](https://github.com/obsidian-tasks-group/obsidian-tasks/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+bug%22+sort%3Acomments-desc) didn't find any similar reports.

### Expected Behavior

When the "User filename as scheduled date" option is turned on, I should be able to manually set the scheduled date.

### Current behaviour

When the scheduled date is changed in the task modal and the Apply button is pressed, the scheduled date reverts to the date on the daily note file.

### Steps to reproduce

1. Turn on "Use filename as scheduled date"
2. Create a task
3. Edit the task and change the scheduled date
4. Click Apply
5. Verify that the scheduled date reverts to the date on the daily note filename

_2022-11-08: See [the comment below](https://github.com/obsidian-tasks-group/obsidian-tasks/issues/1300#issuecomment-1306829403) for an updated set of steps, now we understand that the bug only happens when launching the Edit Tasks modal by clicking on the Pencil icon in a tasks results block. Clare_

### Which Operating Systems are you using?

- [ ] Android
- [ ] iPhone/iPad
- [ ] Linux
- [ ] macOS
- [X] Windows

### Obsidian Version

1.0.3

### Tasks Plugin Version

1.18.0

### Checks

- [X] I have tried it with all other plugins disabled and the error still occurs

### Possible solution

Allow manual scheduled date to override the auto-set date of the filename.


### Workaround

_2022-11-08: Here is what we know about temporary workarounds so far. Clare_

When viewing tasks results blocks, if you want to override the default scheduled date from the file name, please:

1. Click on the backlink, to navigate to the block containing task line.
2. Click on the task you want to edit.
3. **Either** use auto-completion to type in the new scheduled date at the end of the line.
4. **Or** run the `Tasks: Create or edit task` command to open up the Edit task modal.
    - Your edited scheduled date will now be saved correctly.

Pull request:
fix: Editing via Pencil can now change auto-scheduled date
<!--- Provide a general summary of your changes in the Title above -->

# Description

Allows a scheduled date that was set automatically to be modified using the edit icon.

## Motivation and Context

Fixes #1300 

## How has this been tested?

- Added unit tests for the logic. 
- Verified that the scheduled date can be modified using the edit button
- Verified that there are no regressions when modifying a task using the edit dialog

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **Bug fix** (prefix: `fix` - non-breaking change which fixes an issue)
- [ ] **New feature** (prefix: `feat` - non-breaking change which adds functionality)
- [ ] **Breaking change** (prefix: `feat!!` or `fix!!` - fix or feature that would cause existing functionality to not work as expected)
- [ ] **Documentation** (prefix: `docs` - improvements to any documentation content)
- [ ] **Sample vault** (prefix: `vault` - improvements to the [Tasks-Demo sample vault](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/resources/sample_vaults/Tasks-Demo))

Internal changes:

- [ ] **Refactor** (prefix: `refactor` - non-breaking change which only improves the design or structure of existing code, and making no changes to its external behaviour)
- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)
- [ ] **Infrastructure** (prefix: `chore` - examples include GitHub Actions, issue templates)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [ ] My change requires a change to the documentation.
- [ ] I have [updated the documentation](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#updating-documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#maintaining-the-tests).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)


Patch:
diff --git a/src/Commands/CreateOrEdit.ts b/src/Commands/CreateOrEdit.ts
index 46a58623..65b28e94 100644
--- a/src/Commands/CreateOrEdit.ts
+++ b/src/Commands/CreateOrEdit.ts
@@ -23,20 +23,8 @@ export const createOrEdit = (checking: boolean, editor: Editor, view: View, app:
     const line = editor.getLine(lineNumber);
     const task = taskFromLine({ line, path });
 
-    // save the inferred scheduled to compare it later
-    const inferredScheduledDate = task.scheduledDateIsInferred ? task.scheduledDate : null;
-
     const onSubmit = (updatedTasks: Task[]): void => {
-        const serialized = updatedTasks
-            .map((task: Task) => {
-                if (inferredScheduledDate !== null && !inferredScheduledDate.isSame(task.scheduledDate, 'day')) {
-                    // if a fallback date was used before modification, and the scheduled date was modified, we have to mark
-                    // the scheduled date as not inferred anymore.
-                    task = new Task({ ...task, scheduledDateIsInferred: false });
-                }
-
-                return task;
-            })
+        const serialized = DateFallback.removeInferredStatusIfNeeded(task, updatedTasks)
             .map((task: Task) => task.toFileLineString())
             .join('\n');
         editor.setLine(lineNumber, serialized);
diff --git a/src/DateFallback.ts b/src/DateFallback.ts
index 1528e22f..dc13a238 100644
--- a/src/DateFallback.ts
+++ b/src/DateFallback.ts
@@ -119,4 +119,22 @@ export class DateFallback {
             scheduledDateIsInferred,
         });
     }
+
+    /**
+     * Update an array of updated tasks to remove the inferred scheduled date status if the scheduled date has been
+     * modified as compared to the original date
+     */
+    public static removeInferredStatusIfNeeded(originalTask: Task, updatedTasks: Task[]): Task[] {
+        const inferredScheduledDate = originalTask.scheduledDateIsInferred ? originalTask.scheduledDate : null;
+
+        return updatedTasks.map((task: Task) => {
+            if (inferredScheduledDate !== null && !inferredScheduledDate.isSame(task.scheduledDate, 'day')) {
+                // if a fallback date was used before modification, and the scheduled date was modified, we have to mark
+                // the scheduled date as not inferred anymore.
+                task = new Task({ ...task, scheduledDateIsInferred: false });
+            }
+
+            return task;
+        });
+    }
 }
diff --git a/src/QueryRenderer.ts b/src/QueryRenderer.ts
index 67c48065..0c381bc5 100644
--- a/src/QueryRenderer.ts
+++ b/src/QueryRenderer.ts
@@ -9,6 +9,7 @@ import type { GroupHeading } from './Query/GroupHeading';
 import { TaskModal } from './TaskModal';
 import type { TasksEvents } from './TasksEvents';
 import type { Task } from './Task';
+import { DateFallback } from './DateFallback';
 
 export class QueryRenderer {
     private readonly app: App;
@@ -216,7 +217,7 @@ class QueryRenderChild extends MarkdownRenderChild {
             const onSubmit = (updatedTasks: Task[]): void => {
                 replaceTaskWithTasks({
                     originalTask: task,
-                    newTasks: updatedTasks,
+                    newTasks: DateFallback.removeInferredStatusIfNeeded(task, updatedTasks),
                 });
             };
 


Test patch:
diff --git a/tests/DateFallback.test.ts b/tests/DateFallback.test.ts
index 1e4c473c..a980e7a9 100644
--- a/tests/DateFallback.test.ts
+++ b/tests/DateFallback.test.ts
@@ -384,3 +384,44 @@ describe('update fallback date when path is changed', () => {
         expect(updatedTask.scheduledDateIsInferred).toBe(expectedIsInferred);
     });
 });
+
+describe('remove inferred status if scheduled date changed', () => {
+    it('should keep scheduled-date-is-inferred if the date is the same', () => {
+        // arrange
+        const task = new TaskBuilder().scheduledDate('2022-11-11').scheduledDateIsInferred(true).build();
+
+        const updatedTask = new TaskBuilder().scheduledDate('2022-11-11').scheduledDateIsInferred(true).build();
+
+        // act
+        const [processedTask] = DateFallback.removeInferredStatusIfNeeded(task, [updatedTask]);
+
+        // assert
+        expect(processedTask.scheduledDateIsInferred).toBe(true);
+    });
+
+    it('should remove scheduled-date-is-inferred if the date was changed', () => {
+        // arrange
+        const task = new TaskBuilder().scheduledDate('2022-11-11').scheduledDateIsInferred(true).build();
+
+        const updatedTask = new TaskBuilder().scheduledDate('2022-11-15').scheduledDateIsInferred(false).build();
+
+        // act
+        const [processedTask] = DateFallback.removeInferredStatusIfNeeded(task, [updatedTask]);
+
+        // assert
+        expect(processedTask.scheduledDateIsInferred).toBe(false);
+    });
+
+    it('should not set scheduled-date-is-inferred if a scheduled date was added', () => {
+        // arrange
+        const task = new TaskBuilder().scheduledDateIsInferred(false).build();
+
+        const updatedTask = new TaskBuilder().scheduledDate('2022-11-11').scheduledDateIsInferred(false).build();
+
+        // act
+        const [processedTask] = DateFallback.removeInferredStatusIfNeeded(task, [updatedTask]);
+
+        // assert
+        expect(processedTask.scheduledDateIsInferred).toBe(false);
+    });
+});